This code is Script 4a for Kitchel et al. TITLE manuscript.

COPY FROM THIS SCRIPT

(We expect this to be the main analyses in the text)

SESSION INFO TO DO

###Palette for Plotting Palette for plotting all 42 survey units

survey_unit.list <- levels(distances_dissimilarities_allyears.r[,survey_unit])

palette_42 <- c(
  "#5A5156", #AI
  "#DF00DB", #BITS-1
  "#DB8EDA", #BITS-4
  "#F6222E", #CHL
  "#F8A19F", #DFO-NF
  "#16FF32", #DFO-QCS
  "#325A9B", #EBS
  "#3283FE", #EVHOE
  "#FEAF16", #FR-CGFS
  "#fccb6d", #GMEX-Fall
  "#1C8356", #GMEX-Summer
  "#C4451C", #GOA
  "#85660D", #GRL-DE
  "#B0009F", #GSL-N
  "#BF79B8", #GSL-S
  "#1CBE4F", #ICE-GFS
  "#782AB6", #IE-IGFS
  "#90AD1C", #MEDITS
  "#6B003A", #NAM
  "#A75B00", #NEUS-Fall
  "#E3B072", #NEUS-Spring
  "#02E8B6", #NIGFS-1
  "#97E7D5", #NIGFS-4
  "#B00068", #Nor-BTS-3
  "#00B9E3", #NS-IBTS-1
  "#95E2F4", #NS-IBTS-3
  "#B3CE73", #NZ-CHAT
  "#689500", #NZ-ECSI
  "#364d02",#NZ-SUBA
  "#AAF400", #NZ-WCSI
  "#AA0DFE", #PT-IBTS
  "#7f9eb8", #ROCKALL
  "#FA0087", #S-GEORG
  "#DEA0FD", #SCS-Summer
  "#FCEF88", #SEUS-fall
  "#A59405", #SEUS-spring
  "#FCE100", #SEUS-summer
  "#544563", #SWC-IBTS-1
  "#a37fc7", #SWC-IBTS-4
  "#C075A6", #WCANN
  "#BDCDFF", #ZAF-ATL
  "#003EFF"  #ZAF-IND
)

color_link <- data.table(survey_unit = survey_unit.list,hex = palette_42)

Add names for plotting

Total versus balanced BC plot

ggplot(distances_dissimilarities_allyears.r) +
  geom_point(aes(bray_curtis_dissimilarity_total_mean, bray_curtis_dissimilarity_balanced_mean)) +
  geom_abline(slope = 1, intercpet = 0) +
  geom_smooth(aes(bray_curtis_dissimilarity_total_mean, bray_curtis_dissimilarity_balanced_mean)) +
  theme_classic() +
  labs(x = "Total BC dissimilarity",  y = "Balanced changes in abundance/biomass")
Warning: Ignoring unknown parameters: `intercpet`

ggplot(distances_dissimilarities_allyears.r) +
  geom_point(aes(bray_curtis_dissimilarity_total_mean, bray_curtis_dissimilarity_gradient_mean)) +
  geom_abline(slope = 1, intercpet = 0) +
  geom_smooth(aes(bray_curtis_dissimilarity_total_mean, bray_curtis_dissimilarity_gradient_mean)) +
  theme_classic() +
  labs(x = "Total BC dissimilarity",  y = "Abundance/biomass gradient")
Warning: Ignoring unknown parameters: `intercpet`

NA

##Make GAMs

Bray Curtis

bray_curtis_total_gam <- gam(bray_curtis_dissimilarity_total_mean ~ year + s(survey_unit, year, bs = "fs", m = 1),#random smooth
                            data = distances_dissimilarities_allyears.r)

##Make LMERS

Bray These all converged

#running with lme instead of lmer gave same results, but allowed for calculation of p-value
bray_curtis_total_lme <- lme(bray_curtis_dissimilarity_total_mean ~ year_adj, random = (~1 + year_adj|survey_unit),data = distances_dissimilarities_allyears.r)

#but also run with lmer for confint
bray_curtis_total_lmer <- lmer(bray_curtis_dissimilarity_total_mean ~ year_adj + (1 + year_adj|survey_unit),data = distances_dissimilarities_allyears.r)
Warning: Model failed to converge with max|grad| = 0.137452 (tol = 0.002, component 1)
summary(bray_curtis_total_lme)
Linear mixed-effects model fit by REML
  Data: distances_dissimilarities_allyears.r 

Random effects:
 Formula: ~1 + year_adj | survey_unit
 Structure: General positive-definite, Log-Cholesky parametrization
            StdDev      Corr  
(Intercept) 0.108413092 (Intr)
year_adj    0.001972694 -0.763
Residual    0.023981944       

Fixed effects:  bray_curtis_dissimilarity_total_mean ~ year_adj 
 Correlation: 
         (Intr)
year_adj -0.791

Standardized Within-Group Residuals:
       Min         Q1        Med         Q3        Max 
-4.8791736 -0.4684941  0.0317567  0.5158154  4.3793155 

Number of Observations: 897
Number of Groups: 42 
anova(bray_curtis_total_lme)

bray_curtis_total_coefs <- data.table(coef(bray_curtis_total_lme))
bray_curtis_total_coefs[,survey_unit := rownames(coef(bray_curtis_total_lme))][,Year := round(year_adj,5)][,Intercept := round(`(Intercept)`,2)]
View(bray_curtis_total_coefs)

bray_curtis_total_coefs <- bray_curtis_total_coefs[color_link, on = "survey_unit"]

bray_curtis_total_coefs.exp <- bray_curtis_total_coefs[,.(Survey_Name_Season, Intercept, Year)]

#export this table
fwrite(bray_curtis_total_coefs.exp, file = here::here("output","bray_curtis_total_coefs.exp.csv"))

Get LMER model as predictions


# need to sort out year in seq versus overall year models
#new data for lmer
lmer_year <- seq(min(distances_dissimilarities_allyears.r[,year]), max(distances_dissimilarities_allyears.r[,year]), by = 0.1)

lmer_year_adj <- seq(min(distances_dissimilarities_allyears.r[,year_adj]), max(distances_dissimilarities_allyears.r[,year_adj]), by = 0.1)

#predict average lmer
lmer_bray_total_predictions <- data.table(year = lmer_year, year_adj = lmer_year_adj)

#confidence intervals
bray_curtis_total_lmer_confint <- confint(bray_curtis_total_lmer)
Computing profile confidence intervals ...
#populate data table of lmer predictions
lmer_bray_total_predictions[,bray_curtis_lmer_preds := fixef(bray_curtis_total_lmer)[[1]] + fixef(bray_curtis_total_lmer)[[2]] * year_adj][,bray_curtis_lmer_preds_lowerCI := bray_curtis_total_lmer_confint[5] + bray_curtis_total_lmer_confint[6] * year_adj][,bray_curtis_lmer_preds_upperCI := bray_curtis_total_lmer_confint[11] + bray_curtis_total_lmer_confint[12] * year_adj]

###Move forward with Bray Curtis total (others to supplement)

Coefficients for LMER by survey_unit

#unique survey unit year combos
survey_unit_sampling_years <- unique(distances_dissimilarities_allyears.r[,.(survey_unit, year_adj, year, years_sampled)])

# see group coefficients
model_coefs_reduced <- data.table(transform(as.data.frame(ranef(bray_curtis_total_lmer)), lwr = condval - 1.96*condsd, upr = condval + 1.96*condsd))
#https://stackoverflow.com/questions/69805532/extract-the-confidence-intervals-of-lmer-random-effects-plotted-with-dotplotra


#ONLY SLOPES
model_coefs_reduced <- model_coefs_reduced[term == "year_adj",]

model_coefs_reduced[,survey_unit := grp][,year_adj := condval]

#merge with duration of survey
model_coefs_reduced_length <- model_coefs_reduced[survey_unit_sampling_years, on = "survey_unit"]


model_coefs_reduced_length[,years_sampled := as.numeric(years_sampled)][,Directional_Change := ifelse(year_adj > 0, "Differentiation","Homogenization")]

#does it cross zero?
model_coefs_reduced_length[,significant := ifelse(lwr >0 & upr>0,T,ifelse(lwr<0 & upr<0,T,F))]

#significant directional change
model_coefs_reduced_length[,Directional_Change_sig := ifelse(year_adj > 0 & significant == T, "Differentiation",ifelse(year_adj < 0 & significant == T, "Homogenization", "No trend in dissimilarity"))]


#min max distances_dissimilarities
min_bray_reduced <- min(distances_dissimilarities_allyears.r[,bray_curtis_dissimilarity_total_mean], na.rm = T)
max_bray_reduced <- max(distances_dissimilarities_allyears.r[,bray_curtis_dissimilarity_total_mean], na.rm = T)

model_coefs_reduced_length <- model_coefs_reduced_length[color_link, on = "survey_unit"]

#delete any NAs
model_coefs_reduced_length <- na.omit(model_coefs_reduced_length, cols = "significant")

#order table by coefficient
setorder(model_coefs_reduced_length, year_adj)

BC_total_model_coefs_reduced_length.unique <- unique(model_coefs_reduced_length[,.(condval,condsd, lwr, upr, survey_unit, year_adj, years_sampled, Directional_Change, hex, Survey_Name_Season, significant, Directional_Change_sig)]) 

#extract color hexes
#year adj coef order
color_year_adj_order <- BC_total_model_coefs_reduced_length.unique[,hex]

#alphabetical order
BC_total_model_coefs_reduced_length.unique.alpha <- setorder(BC_total_model_coefs_reduced_length.unique, Survey_Name_Season)
color_alpha_order <- BC_total_model_coefs_reduced_length.unique.alpha[,hex]

saveRDS(BC_total_model_coefs_reduced_length.unique, here::here("output","region_stats","BC_total_model_coefs_reduced_length.unique.Rds"))

Bar Plot Coefficient LMER

BC_total_Dissimilarity_Coef_errorbar_reduced <- ggplot() +
    geom_errorbar(data = model_coefs_reduced_length, aes(x = reorder(Survey_Name_Season, year_adj) , y = year_adj, label = Survey_Name_Season, ymin = lwr, ymax = upr), fill = "grey", width = 0) + #add confidence intervals
  geom_point(data = model_coefs_reduced_length, aes(x = reorder(Survey_Name_Season, year_adj) , y = year_adj, label = Survey_Name_Season, size = years_sampled, fill = Directional_Change_sig, color = Directional_Change_sig), stat = 'identity', shape = 21) +
  scale_fill_manual(values = c("white","black","grey"), name = "Dissimilarity trend", guide="none") +
  scale_color_manual(values = c("black","black","grey"), name = "Dissimilarity trend", guide="none") +
  scale_size_binned(range = c(1,8), name = "Survey period length") +
  geom_hline(yintercept = 0) +
  scale_y_continuous(breaks = seq(-0.005, 0.0075, by = 0.0025), labels = c("-0.005","","0", "", "0.005",  "")) +
  xlab("Survey unit") +
  ylab("β-diversity trend") + #total BC dissimilarity trend
  coord_flip() +
  theme_classic() +
  theme(axis.text.y = element_text(colour = color_year_adj_order, face = "bold"), axis.title.y = element_blank(), axis.text.x = element_text(size = 15), axis.title.x = element_text(size = 15), legend.position = c(0.25,0.7), legend.direction = "vertical")
Warning: Ignoring unknown parameters: `fill`Warning: Ignoring unknown aesthetics: labelWarning: Ignoring unknown aesthetics: labelWarning: Vectorized input to `element_text()` is not officially supported.
ℹ Results may be unexpected or may change in future versions of ggplot2.
#pull legend for homogenization
directional_change_legend_plot <- BC_total_Dissimilarity_Coef_errorbar_reduced + 
  scale_fill_manual(values = c("white","black","grey"), name = "Dissimilarity trend") +
  scale_color_manual(values = c("black","black","grey"), name = "Dissimilarity trend") +
  scale_size_binned(range = c(1,8), name = "Survey period length", guide = "none") +
  theme(legend.position = "right", legend.background = element_rect(fill= "transparent")) +
  guides(colour = guide_legend(override.aes = list(size=6)))
Scale for fill is already present.
Adding another scale for fill, which will replace the existing scale.Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.Scale for size is already present.
Adding another scale for size, which will replace the existing scale.
BC_total_Dissimilarity_Coef_errorbar_reduced


#ALT grey scale
BC_total_Dissimilarity_Coef_errorbar_reduced_greyscale <- ggplot() +
    geom_errorbar(data = model_coefs_reduced_length, aes(x = reorder(Survey_Name_Season, year_adj) , y = year_adj, label = Survey_Name_Season, ymin = lwr, ymax = upr), fill = "grey", width = 0) + #add confidence intervals
  geom_point(data = model_coefs_reduced_length, aes(x = reorder(Survey_Name_Season, year_adj) , y = year_adj, label = Survey_Name_Season, size = years_sampled, fill = Directional_Change_sig, color = Directional_Change_sig), stat = 'identity', shape = 21) +
  scale_fill_manual(values = c("white","black","grey"), name = "Dissimilarity trend", guide="none") +
  scale_color_manual(values = c("black","black","grey"), name = "Dissimilarity trend", guide="none") +
  scale_size_binned(range = c(1,8), name = "Survey period length") +
  geom_hline(yintercept = 0) +
  scale_y_continuous(breaks = seq(-0.005, 0.0075, by = 0.0025), labels = c("-0.005","","0", "", "0.005",  "")) +
  xlab("Survey unit") +
  ylab("β-diversity trend") + #total BC dissimilarity trend
  coord_flip() +
  theme_classic() +
  theme(axis.text.y = element_text(face = "bold"), axis.title.y = element_blank(), axis.text.x = element_text(size = 15), axis.title.x = element_text(size = 15), legend.position = c(0.25,0.7), legend.direction = "vertical")
Warning: Ignoring unknown parameters: `fill`Warning: Ignoring unknown aesthetics: labelWarning: Ignoring unknown aesthetics: label

Wavy Line Plot for GAMs

Generate predicted values


#add colors and names to full dissimilarity data table
distances_dissimilarities_allyears.r <- distances_dissimilarities_allyears.r[color_link, on = "survey_unit"]

#generate new data to smooth lines (need year and season survey combinations)
year_survey_unit_expand.dt <- data.table(survey_unit = as.character(NULL), year = as.numeric(NULL), year_adj = as.numeric(NULL ))

for (i in 1:length(survey_unit.list)) {
  #generate year vectors
  survey_unit_years <- unique(distances_dissimilarities_allyears.r[survey_unit == survey_unit.list[i],.(survey_unit, year, year_adj)])
  
  years <- seq(min(survey_unit_years[,year]), max(survey_unit_years[,year]), by = 0.1)
  
  year_adjust <- seq(min(survey_unit_years[,year_adj]), max(survey_unit_years[,year_adj]), by = 0.1)
  
  year_survey_unit_expand.dt_addition <- data.table(survey_unit = survey_unit.list[i], year = years, year_adj = year_adjust)
  
  year_survey_unit_expand.dt <- rbind(year_survey_unit_expand.dt, year_survey_unit_expand.dt_addition)
}

#add colors and names to full year and survey unit combination table
year_survey_unit_expand.dt <- year_survey_unit_expand.dt[color_link, on = "survey_unit"]

Get model as predictions

#for plotting, get model as predictions
bray_curtis_total_gam_predictions <- predict(bray_curtis_total_gam, se.fit = TRUE, newdata = year_survey_unit_expand.dt)

#merge into table
year_survey_unit_expand.dt[,bray_glm_mod_fit := bray_curtis_total_gam_predictions$fit][,bray_glm_mod_fit_SE := bray_curtis_total_gam_predictions$se.fit]

Produce Plot of GAM and mean LMER line

points_wavylines_bray_total_year_reduced_gam_nolmer <- ggplot() +
 # geom_ribbon(data = lmer_bray_total_predictions, aes(x = year, ymin = bray_curtis_lmer_preds_lowerCI, ymax = bray_curtis_lmer_preds_upperCI), fill = "grey", alpha = 0.2) +
  geom_point(data = na.omit(distances_dissimilarities_allyears.r,cols = "year_adj"),
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean,
                 color = Survey_Name_Season), alpha = 0.5, size = 1) +
    geom_line(data = na.omit(year_survey_unit_expand.dt,cols = "year_adj"),
             aes(x = year,
                 y = bray_glm_mod_fit,
                 color = Survey_Name_Season)) +
  geom_ribbon(data = na.omit(year_survey_unit_expand.dt,cols = "year_adj"), aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE, fill =  Survey_Name_Season), alpha=0.1) + #add standard error
 # geom_line(data = lmer_bray_total_predictions, aes(x = year, y = bray_curtis_lmer_preds), color = "black") +
    scale_color_manual(values =  color_alpha_order, name = "Survey Unit") +
  scale_fill_manual(values =  color_alpha_order, guide = "none") +
  theme_classic() +
  lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year])),
       y = c(0.15,0.9)) +
  xlab("Year") +
ylab("total BC dissimilarity") +
  theme(legend.position = "null")

points_wavylines_bray_total_year_reduced_gam_nolmer

ggsave(points_wavylines_bray_total_year_reduced_gam_nolmer, path = here::here("figures"), filename ="points_wavylines_bray_total_year_reduced_gam_nolmer.jpg", height = 5, width = 5, unit = "in")


#with lmer

points_wavylines_bray_total_year_reduced_gam <- ggplot() +
  geom_ribbon(data = lmer_bray_total_predictions, aes(x = year, ymin = bray_curtis_lmer_preds_lowerCI, ymax = bray_curtis_lmer_preds_upperCI), fill = "grey", alpha = 0.3) +
  geom_point(data = na.omit(distances_dissimilarities_allyears.r, cols = "year_adj"),
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean,
                 fill = Survey_Name_Season), alpha = 0.4, size = 1, shape = 21, color = "white") +
    geom_line(data = na.omit(year_survey_unit_expand.dt, cols = "year_adj"),
             aes(x = year,
                 y = bray_glm_mod_fit,
                 color = Survey_Name_Season), alpha = 0.6) +
  geom_ribbon(data = na.omit(year_survey_unit_expand.dt, cols = "year_adj"), aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE, fill =  Survey_Name_Season), alpha=0.1) + #add standard error
  geom_line(data = lmer_bray_total_predictions, aes(x = year, y = bray_curtis_lmer_preds), color = "black") +
    scale_color_manual(values =  color_alpha_order, name = "Survey Unit") +
  scale_fill_manual(values =  color_alpha_order, guide = "none") +
  theme_classic() +
  lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year]))) +
  xlab("Year") +
ylab("β-diversity") +
  theme(legend.position = "null", axis.text = element_text(size = 15), axis.title = element_text(size = 15))

points_wavylines_bray_total_year_reduced_gam

ggsave(points_wavylines_bray_total_year_reduced_gam, path = here::here("figures"), filename ="points_wavylines_bray_total_year_reduced_gam.jpg", height = 6, width = 6, unit = "in")


#ALT
#plot all, but same color scheme (grey)
points_wavylines_bray_total_year_reduced_gam_greyscale <- ggplot() +
  geom_ribbon(data = lmer_bray_total_predictions, aes(x = year, ymin = bray_curtis_lmer_preds_lowerCI, ymax = bray_curtis_lmer_preds_upperCI), fill = "grey", alpha = 0.3) +
  geom_point(data = distances_dissimilarities_allyears.r,
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean,
                 fill = Survey_Name_Season), alpha = 0.4, size = 1, shape = 21, color = "white") +
    geom_line(data = year_survey_unit_expand.dt,
             aes(x = year,
                 y = bray_glm_mod_fit,
                 color = Survey_Name_Season), alpha = 0.6) +
  geom_ribbon(data = year_survey_unit_expand.dt, aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE, fill =  Survey_Name_Season), alpha=0.1) + #add standard error
  geom_line(data = lmer_bray_total_predictions, aes(x = year, y = bray_curtis_lmer_preds), color = "black") +
    scale_color_manual(values =  rep("black", times = length(unique(distances_dissimilarities_allyears.r$Survey_Name_Season))), name = "Survey Unit") +
  scale_fill_manual(values =  rep("black", times = length(unique(distances_dissimilarities_allyears.r$Survey_Name_Season))), guide = "none") +
  theme_classic() +
  lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year]))
       ) +
  xlab("Year") +
ylab("β-diversity") +
  theme(legend.position = "null", axis.text = element_text(size = 15), axis.title = element_text(size = 15))

points_wavylines_bray_total_year_reduced_gam_greyscale

ggsave(points_wavylines_bray_total_year_reduced_gam_greyscale, path = here::here("figures"), filename ="points_wavylines_bray_total_year_reduced_gam_greyscale.jpg", height = 6, width = 6, unit = "in")



#plot each independently for supplement
#all survey names = 
all_survey_names <- sort(unique(color_link$Survey_Name_Season))
#list of plots
points_wavylines_bray_total_year_reduced_gam_individual <- list()
for (i in 1:length(all_survey_names)) {
points_wavylines_bray_total_year_reduced_gam_individual[[i]] <- ggplot() +
  geom_point(data = distances_dissimilarities_allyears.r[Survey_Name_Season == all_survey_names[i]],
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean), alpha = 0.4, color = "black") +
    geom_line(data = year_survey_unit_expand.dt[Survey_Name_Season == all_survey_names[i]],
             aes(x = year,
                 y = bray_glm_mod_fit), alpha = 0.6) +
  geom_ribbon(data = year_survey_unit_expand.dt[Survey_Name_Season == all_survey_names[i]], aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE), alpha=0.1) + #add standard error
  theme_classic() +
#  lims(x = c(min(distances_dissimilarities_allyears.r[Survey_Name_Season == all_survey_names[i],year]),max(distances_dissimilarities_allyears.r[Survey_Name_Season == all_survey_names[i],year])),
#       y = c(0.15,0.9)) +
  xlab("Year") +
ylab("beta-diversity") +
  facet_wrap(~Survey_Name_Season, ncol = 5) +
  theme(legend.position = "null", axis.text = element_text(size = 15), axis.title = element_text(size = 15))

print(points_wavylines_bray_total_year_reduced_gam_individual[[i]])

}

saveRDS(points_wavylines_bray_total_year_reduced_gam_individual, here::here("figures","points_wavylines_bray_total_year_reduced_gam_individual.Rds"))

#print to pdf
library(gridExtra)

ggsave(
   filename = here::here("figures","points_wavylines_bray_total_year_reduced_gam_individual.pdf"), 
   plot = marrangeGrob(points_wavylines_bray_total_year_reduced_gam_individual, nrow=1, ncol=1), 
   width = 8.5, height = 11
)
Warning: Removed 1 rows containing missing values (`geom_point()`).Warning: Removed 1 row containing missing values (`geom_line()`).Warning: no non-missing arguments to max; returning -InfWarning: Removed 1 rows containing missing values (`geom_point()`).Warning: Removed 1 row containing missing values (`geom_line()`).Warning: no non-missing arguments to max; returning -InfWarning: Removed 1 rows containing missing values (`geom_point()`).Warning: Removed 1 row containing missing values (`geom_line()`).Warning: no non-missing arguments to max; returning -Inf

Region by region build up

#just EBS for personal interest
points_wavylines_bray_total_year_reduced_gam_EBS_only <- ggplot() +
  geom_point(data = distances_dissimilarities_allyears.r[survey_unit == "EBS",],
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean), alpha = 0.5, size = 1
            # , 
            # color = BC_total_model_coefs_reduced_length.unique[Survey_Name_Season == "Eastern Bering Sea",hex]
             ) +
  #  geom_line(data = year_survey_unit_expand.dt[survey_unit == "EBS",],
   #          aes(x = year,
    #             y = bray_glm_mod_fit),
     #        color = BC_total_model_coefs_reduced_length.unique[Survey_Name_Season == "Eastern Bering Sea",hex]) +
 # geom_ribbon(data = year_survey_unit_expand.dt[survey_unit == "EBS",], aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE), alpha=0.3, fill = BC_total_model_coefs_reduced_length.unique[Survey_Name_Season == "Eastern Bering Sea",hex]) + #add standard error
 # geom_line(data = lmer_bray_total_predictions, aes(x = year, y = bray_curtis_lmer_preds), color = "black") +
  #  scale_color_manual(name = "Survey Unit") +
 # scale_fill_manual(values =  palette_42, guide = "none") +
 #   lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year])),
 #      y = c(0.15,0.9)) +
  theme_classic() +
  xlab("Year") +
ylab("total BC dissimilarity")

points_wavylines_bray_total_year_reduced_gam_EBS_only

#just one region that's homogenizing (NZ WCSI)
points_wavylines_bray_total_year_reduced_gam_NZ_only <- ggplot() +
  geom_point(data = distances_dissimilarities_allyears.r[survey_unit == "NZ-WCSI",],
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean), alpha = 0.5, size = 1, color = BC_total_model_coefs_reduced_length.unique[Survey_Name_Season == "W Coast S Island NZ",hex]) +
    geom_line(data = year_survey_unit_expand.dt[survey_unit == "NZ-WCSI",],
             aes(x = year,
                 y = bray_glm_mod_fit),
             color = BC_total_model_coefs_reduced_length.unique[Survey_Name_Season == "W Coast S Island NZ",hex]) +
  geom_ribbon(data = year_survey_unit_expand.dt[survey_unit == "NZ-WCSI",], aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE), alpha=0.3, fill = BC_total_model_coefs_reduced_length.unique[Survey_Name_Season == "W Coast S Island NZ",hex]) + #add standard error
 # geom_line(data = lmer_bray_total_predictions, aes(x = year, y = bray_curtis_lmer_preds), color = "black") +
    scale_color_manual(name = "Survey Unit") +
 # scale_fill_manual(values =  palette_42, guide = "none") +
    lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year])),
       y = c(0.15,0.9)) +
  theme_classic() +
  xlab("Year") +
ylab("total BC dissimilarity")

points_wavylines_bray_total_year_reduced_gam_NZ_only

#just two regions, another that's differentiating (SEUS Summer)

points_wavylines_bray_total_year_reduced_gam_NZ_SEUS_Summer_only <- ggplot() +
  geom_point(data = distances_dissimilarities_allyears.r[survey_unit %in% c("NZ-WCSI","SEUS-summer"),],
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean,
                 color = Survey_Name_Season), alpha = 0.5, size = 1) +
    geom_line(data = year_survey_unit_expand.dt[survey_unit %in% c("NZ-WCSI","SEUS-summer"),],
             aes(x = year,
                 y = bray_glm_mod_fit,
                 color = Survey_Name_Season)) +
  geom_ribbon(data = year_survey_unit_expand.dt[survey_unit %in% c("NZ-WCSI","SEUS-summer"),], aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE, fill = survey_unit), alpha=0.3) + #add standard error
 # geom_line(data = lmer_bray_total_predictions, aes(x = year, y = bray_curtis_lmer_preds), color = "black") +
    scale_color_manual(name = "Survey Unit", values = c(BC_total_model_coefs_reduced_length.unique[Survey_Name_Season %in% c("W Coast S Island NZ","SE US Summer"),hex])) +
  scale_fill_manual(guide = "none", values = c(BC_total_model_coefs_reduced_length.unique[Survey_Name_Season %in% c("W Coast S Island NZ","SE US Summer"),hex])) +
    lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year])),
       y = c(0.15,0.9)) +
  theme_classic() +
  xlab("Year") +
ylab("total BC dissimilarity") +
  theme(legend.position = "null")

points_wavylines_bray_total_year_reduced_gam_NZ_SEUS_Summer_only

#just three regions, another one that's stable, (Canada Scotian Shelf)

points_wavylines_bray_total_year_reduced_gam_NZ_SEUS_ScoShelf_only <- ggplot() +
  geom_point(data = distances_dissimilarities_allyears.r[survey_unit %in% c("NZ-WCSI","SEUS-summer", "SCS-SUMMER"),],
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean,
                 color = Survey_Name_Season), alpha = 0.5, size = 1) +
    geom_line(data = year_survey_unit_expand.dt[survey_unit %in% c("NZ-WCSI","SEUS-summer","SCS-SUMMER"),],
             aes(x = year,
                 y = bray_glm_mod_fit,
                 color = Survey_Name_Season)) +
  geom_ribbon(data = year_survey_unit_expand.dt[survey_unit %in% c("NZ-WCSI","SEUS-summer","SCS-SUMMER"),], aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE, fill = Survey_Name_Season), alpha=0.3) + #add standard error
 # geom_line(data = lmer_bray_total_predictions, aes(x = year, y = bray_curtis_lmer_preds), color = "black") +
    scale_color_manual(name = "Survey Unit", values = c(BC_total_model_coefs_reduced_length.unique[Survey_Name_Season %in% c("W Coast S Island NZ","SE US Summer","Scotian Shelf"),hex])) +
  scale_fill_manual(guide = "none", values = c(BC_total_model_coefs_reduced_length.unique[Survey_Name_Season %in% c("W Coast S Island NZ","SE US Summer","Scotian Shelf"),hex])) +
    lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year])),
       y = c(0.15,0.9)) +
  theme_classic() +
  xlab("Year") +
ylab("total BC dissimilarity") +
  theme(legend.position = "null")

points_wavylines_bray_total_year_reduced_gam_NZ_SEUS_ScoShelf_only

ggsave(points_wavylines_bray_total_year_reduced_gam_NZ_only, path = here::here("figures"), filename ="points_wavylines_bray_total_year_reduced_gam_NZ_only.jpg", height = 5, width = 5, unit = "in")
ggsave(points_wavylines_bray_total_year_reduced_gam_EBS_only, path = here::here("figures"), filename ="points_wavylines_bray_total_year_reduced_gam_EBS_only.jpg", height = 5, width = 9, unit = "in")
ggsave(points_wavylines_bray_total_year_reduced_gam_NZ_SEUS_Summer_only, path = here::here("figures"), filename ="points_wavylines_bray_total_year_reduced_gam_NZ_SEUS_Summer_only.jpg", height = 5, width = 5, unit = "in")
ggsave(points_wavylines_bray_total_year_reduced_gam_NZ_SEUS_ScoShelf_only, path = here::here("figures"), filename ="points_wavylines_bray_total_year_reduced_gam_NZ_SEUS_ScoShelf_only.jpg", height = 5, width = 5, unit = "in")

Merge BC versus Year plot with GAMS and Region vs. coefficient plot for LMERs


BC_total_GAM_LMER_merge_legend <- ggdraw(xlim = c(0, 40.5), ylim = c(0, 21)) +
    draw_plot(points_wavylines_bray_total_year_reduced_gam,
                                         x = 1, y = 1, width = 20, height = 20) +
    draw_plot(BC_total_Dissimilarity_Coef_errorbar_reduced +
        theme(legend.key.size = unit(0.5, 'cm'), #change legend key size
        legend.title = element_text(size=16), #change legend title font size
        legend.text = element_text(size=14)), #change legend text font size),
                                         x = 20, y = 1, width =19, height = 20) +
    draw_plot(get_legend(directional_change_legend_plot + 
      theme(legend.key.size = unit(0.5, 'cm'), #change legend key size
        legend.title = element_text(size=15), #change legend title font size
        legend.text = element_text(size=13))), #change legend text font size)
                                       x = 27.4, y = 10, width = 3, height = 2) +
  geom_text(aes(x = 2, y = 20.7), label = ("a."), size =8, fontface = "bold") +
  geom_text(aes(x =20, y = 20.7), label = ("b."), size =8, fontface = "bold")


ggsave(BC_total_GAM_LMER_merge_legend, path = here::here("figures"), filename = "BC_total_GAM_LMER_merge_legend.png", height = 8, width = 14, units = "in")

#ALT GREY SCALE
BC_total_GAM_LMER_merge_legend_greyscale <- ggdraw(xlim = c(0, 40.5), ylim = c(0, 21)) +
    draw_plot(points_wavylines_bray_total_year_reduced_gam_greyscale,
                                         x = 1, y = 1, width = 20, height = 20) +
    draw_plot(BC_total_Dissimilarity_Coef_errorbar_reduced_greyscale +
        theme(legend.key.size = unit(0.5, 'cm'), #change legend key size
        legend.title = element_text(size=16), #change legend title font size
        legend.text = element_text(size=14)), #change legend text font size),
                                         x = 20, y = 1, width = 19, height = 20) +
    draw_plot(get_legend(directional_change_legend_plot + 
      theme(legend.key.size = unit(0.5, 'cm'), #change legend key size
        legend.title = element_text(size=15), #change legend title font size
        legend.text = element_text(size=13))), #change legend text font size)
                                x = 27.4, y = 10, width = 3, height = 2) +
  geom_text(aes(x = 2, y = 20.7), label = ("a."), size =8, fontface = "bold") +
  geom_text(aes(x =20, y = 20.7), label = ("b."), size =8, fontface = "bold")

ggsave(BC_total_GAM_LMER_merge_legend_greyscale, path = here::here("figures"), filename = "BC_total_GAM_LMER_merge_legend_greyscale.png", height = 8, width = 14, units = "in")
LS0tCnRpdGxlOiAiWWVhciBUT1RBTCBEaXNzaW1pbGFyaXR5IE1vZGVscyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBjb2RlIGlzIFNjcmlwdCA0YSAgZm9yIEtpdGNoZWwgZXQgYWwuIFRJVExFIG1hbnVzY3JpcHQuCgpDT1BZIEZST00gVEhJUyBTQ1JJUFQKCihXZSBleHBlY3QgdGhpcyB0byBiZSB0aGUgbWFpbiBhbmFseXNlcyBpbiB0aGUgdGV4dCkKCi0gVGhpcyBwcm9qZWN0IGlzIGEgY29sbGFib3JhdGl2ZSBlZmZvcnQgdG8gZGVzY3JpYmUgY2hhbmdlcyBpbiB0YXhvbm9taWMgY29tcG9zaXRpb24gIG9mIGZpc2ggY29tbXVuaXRpZXMgYXJvdW5kIHRoZSB3b3JsZC0tYXMgc2FtcGxlZCBieSBib3R0b20gdHJhd2wgc3VydmV5cy4KCi0gQ29kZSBieSBab8OrIEouIEtpdGNoZWwKClNFU1NJT04gSU5GTyBUTyBETwoKYGBge3Igc2V0dXB9CmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeSh2ZWdhbikKbGlicmFyeShzZikKbGlicmFyeShjb25jYXZlbWFuKSAjcG9seWdvbiBhcm91bmQgcG9pbnRzCmxpYnJhcnkoYmV0YXBhcnQpICNhbGxvd3MgdXMgdG8gcGFydGl0aW9uIGJldGEgZGl2ZXJzaXR5CmxpYnJhcnkoZ2Vvc3BoZXJlKQpsaWJyYXJ5KGdncHVicikgI3N0YXRfcmVnbGluZV9lcXVhdGlvbgpsaWJyYXJ5KG5sbWUpCmxpYnJhcnkobWdjdikgI3RvIG1ha2UgZ2FtCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShsbWU0KQoKI1B1bGwgRGlzc2ltaWxhcml0eSBNZWFucwpkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnIgPC0gcmVhZFJEUyhoZXJlOjpoZXJlKCJvdXRwdXQiLCAiZGlzc2ltaWxhcml0aWVzIiwgImRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuci5yZHMiKSkKCiNtYWtlIHN1cnZleSBhbmQgc3VydmV5IHVuaXQgZmFjdG9ycwpkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLHN1cnZleTo9ZmFjdG9yKHN1cnZleSldWyxzdXJ2ZXlfdW5pdDo9ZmFjdG9yKHN1cnZleV91bml0KV0KCiNhZGp1c3QgeWVhcnMKZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyX2FkaiA6PSB5ZWFyLW1pbih5ZWFyKSsxXQoKI2FkZCBuZXcgdmFyaWFibGUgZm9yIHllYXIgaW4gc2VxdWVuY2UgcGVyIHJlZ2lvbgpkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLGZpcnN0X3llYXIgOj0gbWluKHllYXIpLC4oc3VydmV5X3VuaXQpXQpkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLGxhc3RfeWVhciA6PSBtYXgoeWVhciksLihzdXJ2ZXlfdW5pdCldCgojZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyX2luX3NlcSA6PSB5ZWFyLWZpcnN0X3llYXIrMV0KCmRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcnNfc2FtcGxlZCA6PSBsYXN0X3llYXItZmlyc3RfeWVhcisxXQoKCmBgYAoKIyMjUGFsZXR0ZSBmb3IgUGxvdHRpbmcKUGFsZXR0ZSBmb3IgcGxvdHRpbmcgYWxsIDQyIHN1cnZleSB1bml0cwpgYGB7ciBsaW5rIGNvbG9ycyB0byBzdXJ2ZXkgdW5pdHN9CnN1cnZleV91bml0Lmxpc3QgPC0gbGV2ZWxzKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclssc3VydmV5X3VuaXRdKQoKcGFsZXR0ZV80MiA8LSBjKAogICIjNUE1MTU2IiwgI0FJCiAgIiNERjAwREIiLCAjQklUUy0xCiAgIiNEQjhFREEiLCAjQklUUy00CiAgIiNGNjIyMkUiLCAjQ0hMCiAgIiNGOEExOUYiLCAjREZPLU5GCiAgIiMxNkZGMzIiLCAjREZPLVFDUwogICIjMzI1QTlCIiwgI0VCUwogICIjMzI4M0ZFIiwgI0VWSE9FCiAgIiNGRUFGMTYiLCAjRlItQ0dGUwogICIjZmNjYjZkIiwgI0dNRVgtRmFsbAogICIjMUM4MzU2IiwgI0dNRVgtU3VtbWVyCiAgIiNDNDQ1MUMiLCAjR09BCiAgIiM4NTY2MEQiLCAjR1JMLURFCiAgIiNCMDAwOUYiLCAjR1NMLU4KICAiI0JGNzlCOCIsICNHU0wtUwogICIjMUNCRTRGIiwgI0lDRS1HRlMKICAiIzc4MkFCNiIsICNJRS1JR0ZTCiAgIiM5MEFEMUMiLCAjTUVESVRTCiAgIiM2QjAwM0EiLCAjTkFNCiAgIiNBNzVCMDAiLCAjTkVVUy1GYWxsCiAgIiNFM0IwNzIiLCAjTkVVUy1TcHJpbmcKICAiIzAyRThCNiIsICNOSUdGUy0xCiAgIiM5N0U3RDUiLCAjTklHRlMtNAogICIjQjAwMDY4IiwgI05vci1CVFMtMwogICIjMDBCOUUzIiwgI05TLUlCVFMtMQogICIjOTVFMkY0IiwgI05TLUlCVFMtMwogICIjQjNDRTczIiwgI05aLUNIQVQKICAiIzY4OTUwMCIsICNOWi1FQ1NJCiAgIiMzNjRkMDIiLCNOWi1TVUJBCiAgIiNBQUY0MDAiLCAjTlotV0NTSQogICIjQUEwREZFIiwgI1BULUlCVFMKICAiIzdmOWViOCIsICNST0NLQUxMCiAgIiNGQTAwODciLCAjUy1HRU9SRwogICIjREVBMEZEIiwgI1NDUy1TdW1tZXIKICAiI0ZDRUY4OCIsICNTRVVTLWZhbGwKICAiI0E1OTQwNSIsICNTRVVTLXNwcmluZwogICIjRkNFMTAwIiwgI1NFVVMtc3VtbWVyCiAgIiM1NDQ1NjMiLCAjU1dDLUlCVFMtMQogICIjYTM3ZmM3IiwgI1NXQy1JQlRTLTQKICAiI0MwNzVBNiIsICNXQ0FOTgogICIjQkRDREZGIiwgI1pBRi1BVEwKICAiIzAwM0VGRiIgICNaQUYtSU5ECikKCmNvbG9yX2xpbmsgPC0gZGF0YS50YWJsZShzdXJ2ZXlfdW5pdCA9IHN1cnZleV91bml0Lmxpc3QsaGV4ID0gcGFsZXR0ZV80MikKYGBgCgpBZGQgbmFtZXMgZm9yIHBsb3R0aW5nCmBgYHtyIGFkZCBuYW1lcyBmb3IgcGxvdHRpbmd9CgpuYW1lX2hlbHBlciA8LSBkYXRhLnRhYmxlKFN1cnZleV9OYW1lX1NlYXNvbiA9IGMoIkFsZXV0aWFuIElzbGFuZHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQmFsdGljIFNlYSBRMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCYWx0aWMgU2VhIFE0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNoaWxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5ld2ZvdW5kbGFuZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJRdWVlbiBDaGFybG90dGUgU291bmQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRWFzdGVybiBCZXJpbmcgU2VhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJheSBvZiBCaXNjYXkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRW5nbGlzaCBDaGFubmVsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkd1bGYgb2YgTWV4aWNvIFN1bW1lciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHdWxmIG9mIEFsYXNrYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcmVlbmxhbmQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTiBHdWxmIG9mIFN0LiBMYXdyZW5jZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTIEd1bGYgb2YgU3QuIExhd3JlbmNlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkljZWxhbmQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSXJpc2ggU2VhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1lZGl0ZXJyYW5lYW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTmFtaWJpYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJORSBVUyBGYWxsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5FIFVTIFNwcmluZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOIElyZWxhbmQgUTEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTiBJcmVsYW5kIFE0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJhcmVudHMgU2VhIE5vcndheSBRMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOIFNlYSBRMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOIFNlYSBRMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDaGF0aGFtIFJpc2UgTloiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRSBDb2FzdCBTIElzbGFuZCBOWiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXIENvYXN0IFMgSXNsYW5kIE5aIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBvcnR1Z2FsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlMgR2VvcmdpYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2NvdGlhbiBTaGVsZiBTdW1tZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNFIFVTIEZhbGwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNFIFVTIFNwcmluZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU0UgVVMgU3VtbWVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXIENvYXN0IFVTIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBdGxhbnRpYyBPY2VhbiBaQSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSW5kaWFuIE9jZWFuIFpBIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUm9ja2FsbCBQbGF0ZWF1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTY290bGFuZCBTaGVsZiBTZWEgUTEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNjb3RsYW5kIFNoZWxmIFNlYSBRNCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRmFsa2xhbmQgSXNsYW5kcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3VsZiBvZiBNZXhpY28gRmFsbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQmFyZW50cyBTZWEgTm9yd2F5IFExIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTdWItQXJjdGljIE5aIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTY290aWFuIFNoZWxmIFNwcmluZyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHN1cnZleV91bml0ID0gYygKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBSSIsICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCSVRTLTEiLCAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCSVRTLTQiLCAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDSEwiLCAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJERk8tTkYiLCAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJERk8tUUNTIiwgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFQlMiLCAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFVkhPRSIsICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGUi1DR0ZTIiwgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHTUVYLVN1bW1lciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR09BIiwgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR1JMLURFIiwgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR1NMLU4iLCAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR1NMLVMiLCAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSUNFLUdGUyIsICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSUUtSUdGUyIsICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTUVESVRTIiwgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTkFNIiwgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTkVVUy1GYWxsIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTkVVUy1TcHJpbmciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5JR0ZTLTEiLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5JR0ZTLTQiLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5vci1CVFMtMyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5TLUlCVFMtMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5TLUlCVFMtMyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5aLUNIQVQiLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5aLUVDU0kiLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5aLVdDU0kiLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBULUlCVFMiLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlMtR0VPUkciLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNDUy1TVU1NRVIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNFVVMtZmFsbCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNFVVMtc3ByaW5nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTRVVTLXN1bW1lciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV0NBTk4iLCAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiWkFGLUFUTCIsICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiWkFGLUlORCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUk9DS0FMTCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU1dDLUlCVFMtMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU1dDLUlCVFMtNCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRkFMSyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR01FWC1GYWxsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOb3ItQlRTLTEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5aLVNVQkEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNDUy1TUFJJTkciCiAgICAgICAgICAgICAgICAgICAgICAgICAgKSkKCgpjb2xvcl9saW5rIDwtIGNvbG9yX2xpbmtbbmFtZV9oZWxwZXIsIG9uID0gInN1cnZleV91bml0Il0KCmBgYAoKVG90YWwgdmVyc3VzIGJhbGFuY2VkIEJDIHBsb3QKYGBge3J9CmdncGxvdChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnIpICsKICBnZW9tX3BvaW50KGFlcyhicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X3RvdGFsX21lYW4sIGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfYmFsYW5jZWRfbWVhbikpICsKICBnZW9tX2FibGluZShzbG9wZSA9IDEsIGludGVyY3BldCA9IDApICsKICBnZW9tX3Ntb290aChhZXMoYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuLCBicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X2JhbGFuY2VkX21lYW4pKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICBsYWJzKHggPSAiVG90YWwgQkMgZGlzc2ltaWxhcml0eSIsICB5ID0gIkJhbGFuY2VkIGNoYW5nZXMgaW4gYWJ1bmRhbmNlL2Jpb21hc3MiKQoKZ2dwbG90KGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMucikgKwogIGdlb21fcG9pbnQoYWVzKGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfdG90YWxfbWVhbiwgYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV9ncmFkaWVudF9tZWFuKSkgKwogIGdlb21fYWJsaW5lKHNsb3BlID0gMSwgaW50ZXJjcGV0ID0gMCkgKwogIGdlb21fc21vb3RoKGFlcyhicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X3RvdGFsX21lYW4sIGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfZ3JhZGllbnRfbWVhbikpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGxhYnMoeCA9ICJUb3RhbCBCQyBkaXNzaW1pbGFyaXR5IiwgIHkgPSAiQWJ1bmRhbmNlL2Jpb21hc3MgZ3JhZGllbnQiKQogIApgYGAKCgojI01ha2UgR0FNcwoKQnJheSBDdXJ0aXMKYGBge3IgYnJheSBjdXJ0aXMgZ2Ftc30KYnJheV9jdXJ0aXNfdG90YWxfZ2FtIDwtIGdhbShicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X3RvdGFsX21lYW4gfiB5ZWFyICsgcyhzdXJ2ZXlfdW5pdCwgeWVhciwgYnMgPSAiZnMiLCBtID0gMSksI3JhbmRvbSBzbW9vdGgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnIpCgpgYGAKCgojI01ha2UgTE1FUlMKCkJyYXkKKlRoZXNlIGFsbCBjb252ZXJnZWQqCmBgYHtyIGJyYXl9CiNydW5uaW5nIHdpdGggbG1lIGluc3RlYWQgb2YgbG1lciBnYXZlIHNhbWUgcmVzdWx0cywgYnV0IGFsbG93ZWQgZm9yIGNhbGN1bGF0aW9uIG9mIHAtdmFsdWUKYnJheV9jdXJ0aXNfdG90YWxfbG1lIDwtIGxtZShicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X3RvdGFsX21lYW4gfiB5ZWFyX2FkaiwgcmFuZG9tID0gKH4xICsgeWVhcl9hZGp8c3VydmV5X3VuaXQpLGRhdGEgPSBkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnIpCgojYnV0IGFsc28gcnVuIHdpdGggbG1lciBmb3IgY29uZmludApicmF5X2N1cnRpc190b3RhbF9sbWVyIDwtIGxtZXIoYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuIH4geWVhcl9hZGogKyAoMSArIHllYXJfYWRqfHN1cnZleV91bml0KSxkYXRhID0gZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yKQoKc3VtbWFyeShicmF5X2N1cnRpc190b3RhbF9sbWUpCmFub3ZhKGJyYXlfY3VydGlzX3RvdGFsX2xtZSkKCmJyYXlfY3VydGlzX3RvdGFsX2NvZWZzIDwtIGRhdGEudGFibGUoY29lZihicmF5X2N1cnRpc190b3RhbF9sbWUpKQpicmF5X2N1cnRpc190b3RhbF9jb2Vmc1ssc3VydmV5X3VuaXQgOj0gcm93bmFtZXMoY29lZihicmF5X2N1cnRpc190b3RhbF9sbWUpKV1bLFllYXIgOj0gcm91bmQoeWVhcl9hZGosNSldWyxJbnRlcmNlcHQgOj0gcm91bmQoYChJbnRlcmNlcHQpYCwyKV0KVmlldyhicmF5X2N1cnRpc190b3RhbF9jb2VmcykKCmJyYXlfY3VydGlzX3RvdGFsX2NvZWZzIDwtIGJyYXlfY3VydGlzX3RvdGFsX2NvZWZzW2NvbG9yX2xpbmssIG9uID0gInN1cnZleV91bml0Il0KCmJyYXlfY3VydGlzX3RvdGFsX2NvZWZzLmV4cCA8LSBicmF5X2N1cnRpc190b3RhbF9jb2Vmc1ssLihTdXJ2ZXlfTmFtZV9TZWFzb24sIEludGVyY2VwdCwgWWVhcildCgojZXhwb3J0IHRoaXMgdGFibGUKZndyaXRlKGJyYXlfY3VydGlzX3RvdGFsX2NvZWZzLmV4cCwgZmlsZSA9IGhlcmU6OmhlcmUoIm91dHB1dCIsImJyYXlfY3VydGlzX3RvdGFsX2NvZWZzLmV4cC5jc3YiKSkKYGBgCgpHZXQgTE1FUiBtb2RlbCBhcyBwcmVkaWN0aW9ucwpgYGB7cn0KCiMgbmVlZCB0byBzb3J0IG91dCB5ZWFyIGluIHNlcSB2ZXJzdXMgb3ZlcmFsbCB5ZWFyIG1vZGVscwojbmV3IGRhdGEgZm9yIGxtZXIKbG1lcl95ZWFyIDwtIHNlcShtaW4oZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyXSksIG1heChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLHllYXJdKSwgYnkgPSAwLjEpCgpsbWVyX3llYXJfYWRqIDwtIHNlcShtaW4oZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyX2Fkal0pLCBtYXgoZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyX2Fkal0pLCBieSA9IDAuMSkKCiNwcmVkaWN0IGF2ZXJhZ2UgbG1lcgpsbWVyX2JyYXlfdG90YWxfcHJlZGljdGlvbnMgPC0gZGF0YS50YWJsZSh5ZWFyID0gbG1lcl95ZWFyLCB5ZWFyX2FkaiA9IGxtZXJfeWVhcl9hZGopCgojY29uZmlkZW5jZSBpbnRlcnZhbHMKYnJheV9jdXJ0aXNfdG90YWxfbG1lcl9jb25maW50IDwtIGNvbmZpbnQoYnJheV9jdXJ0aXNfdG90YWxfbG1lcikKCiNwb3B1bGF0ZSBkYXRhIHRhYmxlIG9mIGxtZXIgcHJlZGljdGlvbnMKbG1lcl9icmF5X3RvdGFsX3ByZWRpY3Rpb25zWyxicmF5X2N1cnRpc19sbWVyX3ByZWRzIDo9IGZpeGVmKGJyYXlfY3VydGlzX3RvdGFsX2xtZXIpW1sxXV0gKyBmaXhlZihicmF5X2N1cnRpc190b3RhbF9sbWVyKVtbMl1dICogeWVhcl9hZGpdWyxicmF5X2N1cnRpc19sbWVyX3ByZWRzX2xvd2VyQ0kgOj0gYnJheV9jdXJ0aXNfdG90YWxfbG1lcl9jb25maW50WzVdICsgYnJheV9jdXJ0aXNfdG90YWxfbG1lcl9jb25maW50WzZdICogeWVhcl9hZGpdWyxicmF5X2N1cnRpc19sbWVyX3ByZWRzX3VwcGVyQ0kgOj0gYnJheV9jdXJ0aXNfdG90YWxfbG1lcl9jb25maW50WzExXSArIGJyYXlfY3VydGlzX3RvdGFsX2xtZXJfY29uZmludFsxMl0gKiB5ZWFyX2Fkal0KYGBgCgoKCiMjI01vdmUgZm9yd2FyZCB3aXRoIEJyYXkgQ3VydGlzIHRvdGFsIChvdGhlcnMgdG8gc3VwcGxlbWVudCkKCgpDb2VmZmljaWVudHMgZm9yIExNRVIgYnkgc3VydmV5X3VuaXQKYGBge3J9CiN1bmlxdWUgc3VydmV5IHVuaXQgeWVhciBjb21ib3MKc3VydmV5X3VuaXRfc2FtcGxpbmdfeWVhcnMgPC0gdW5pcXVlKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclssLihzdXJ2ZXlfdW5pdCwgeWVhcl9hZGosIHllYXIsIHllYXJzX3NhbXBsZWQpXSkKCiMgc2VlIGdyb3VwIGNvZWZmaWNpZW50cwptb2RlbF9jb2Vmc19yZWR1Y2VkIDwtIGRhdGEudGFibGUodHJhbnNmb3JtKGFzLmRhdGEuZnJhbWUocmFuZWYoYnJheV9jdXJ0aXNfdG90YWxfbG1lcikpLCBsd3IgPSBjb25kdmFsIC0gMS45Nipjb25kc2QsIHVwciA9IGNvbmR2YWwgKyAxLjk2KmNvbmRzZCkpCiNodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82OTgwNTUzMi9leHRyYWN0LXRoZS1jb25maWRlbmNlLWludGVydmFscy1vZi1sbWVyLXJhbmRvbS1lZmZlY3RzLXBsb3R0ZWQtd2l0aC1kb3RwbG90cmEKCgojT05MWSBTTE9QRVMKbW9kZWxfY29lZnNfcmVkdWNlZCA8LSBtb2RlbF9jb2Vmc19yZWR1Y2VkW3Rlcm0gPT0gInllYXJfYWRqIixdCgptb2RlbF9jb2Vmc19yZWR1Y2VkWyxzdXJ2ZXlfdW5pdCA6PSBncnBdWyx5ZWFyX2FkaiA6PSBjb25kdmFsXQoKI21lcmdlIHdpdGggZHVyYXRpb24gb2Ygc3VydmV5Cm1vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoIDwtIG1vZGVsX2NvZWZzX3JlZHVjZWRbc3VydmV5X3VuaXRfc2FtcGxpbmdfeWVhcnMsIG9uID0gInN1cnZleV91bml0Il0KCgptb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aFsseWVhcnNfc2FtcGxlZCA6PSBhcy5udW1lcmljKHllYXJzX3NhbXBsZWQpXVssRGlyZWN0aW9uYWxfQ2hhbmdlIDo9IGlmZWxzZSh5ZWFyX2FkaiA+IDAsICJEaWZmZXJlbnRpYXRpb24iLCJIb21vZ2VuaXphdGlvbiIpXQoKI2RvZXMgaXQgY3Jvc3MgemVybz8KbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGhbLHNpZ25pZmljYW50IDo9IGlmZWxzZShsd3IgPjAgJiB1cHI+MCxULGlmZWxzZShsd3I8MCAmIHVwcjwwLFQsRikpXQoKI3NpZ25pZmljYW50IGRpcmVjdGlvbmFsIGNoYW5nZQptb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aFssRGlyZWN0aW9uYWxfQ2hhbmdlX3NpZyA6PSBpZmVsc2UoeWVhcl9hZGogPiAwICYgc2lnbmlmaWNhbnQgPT0gVCwgIkRpZmZlcmVudGlhdGlvbiIsaWZlbHNlKHllYXJfYWRqIDwgMCAmIHNpZ25pZmljYW50ID09IFQsICJIb21vZ2VuaXphdGlvbiIsICJObyB0cmVuZCBpbiBkaXNzaW1pbGFyaXR5IikpXQoKCiNtaW4gbWF4IGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXMKbWluX2JyYXlfcmVkdWNlZCA8LSBtaW4oZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyxicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X3RvdGFsX21lYW5dLCBuYS5ybSA9IFQpCm1heF9icmF5X3JlZHVjZWQgPC0gbWF4KGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclssYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuXSwgbmEucm0gPSBUKQoKbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGggPC0gbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGhbY29sb3JfbGluaywgb24gPSAic3VydmV5X3VuaXQiXQoKI2RlbGV0ZSBhbnkgTkFzCm1vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoIDwtIG5hLm9taXQobW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgsIGNvbHMgPSAic2lnbmlmaWNhbnQiKQoKI29yZGVyIHRhYmxlIGJ5IGNvZWZmaWNpZW50CnNldG9yZGVyKG1vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLCB5ZWFyX2FkaikKCkJDX3RvdGFsX21vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLnVuaXF1ZSA8LSB1bmlxdWUobW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGhbLC4oY29uZHZhbCxjb25kc2QsIGx3ciwgdXByLCBzdXJ2ZXlfdW5pdCwgeWVhcl9hZGosIHllYXJzX3NhbXBsZWQsIERpcmVjdGlvbmFsX0NoYW5nZSwgaGV4LCBTdXJ2ZXlfTmFtZV9TZWFzb24sIHNpZ25pZmljYW50LCBEaXJlY3Rpb25hbF9DaGFuZ2Vfc2lnKV0pIAoKI2V4dHJhY3QgY29sb3IgaGV4ZXMKI3llYXIgYWRqIGNvZWYgb3JkZXIKY29sb3JfeWVhcl9hZGpfb3JkZXIgPC0gQkNfdG90YWxfbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgudW5pcXVlWyxoZXhdCgojYWxwaGFiZXRpY2FsIG9yZGVyCkJDX3RvdGFsX21vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLnVuaXF1ZS5hbHBoYSA8LSBzZXRvcmRlcihCQ190b3RhbF9tb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aC51bmlxdWUsIFN1cnZleV9OYW1lX1NlYXNvbikKY29sb3JfYWxwaGFfb3JkZXIgPC0gQkNfdG90YWxfbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgudW5pcXVlLmFscGhhWyxoZXhdCgpzYXZlUkRTKEJDX3RvdGFsX21vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLnVuaXF1ZSwgaGVyZTo6aGVyZSgib3V0cHV0IiwicmVnaW9uX3N0YXRzIiwiQkNfdG90YWxfbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgudW5pcXVlLlJkcyIpKQpgYGAKCkJhciBQbG90IENvZWZmaWNpZW50IExNRVIKYGBge3IgYmFyIHBsb3Qgb2YgY29lZmZpY2llbnRzfQpCQ190b3RhbF9EaXNzaW1pbGFyaXR5X0NvZWZfZXJyb3JiYXJfcmVkdWNlZCA8LSBnZ3Bsb3QoKSArCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBtb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aCwgYWVzKHggPSByZW9yZGVyKFN1cnZleV9OYW1lX1NlYXNvbiwgeWVhcl9hZGopICwgeSA9IHllYXJfYWRqLCBsYWJlbCA9IFN1cnZleV9OYW1lX1NlYXNvbiwgeW1pbiA9IGx3ciwgeW1heCA9IHVwciksIGZpbGwgPSAiZ3JleSIsIHdpZHRoID0gMCkgKyAjYWRkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzCiAgZ2VvbV9wb2ludChkYXRhID0gbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgsIGFlcyh4ID0gcmVvcmRlcihTdXJ2ZXlfTmFtZV9TZWFzb24sIHllYXJfYWRqKSAsIHkgPSB5ZWFyX2FkaiwgbGFiZWwgPSBTdXJ2ZXlfTmFtZV9TZWFzb24sIHNpemUgPSB5ZWFyc19zYW1wbGVkLCBmaWxsID0gRGlyZWN0aW9uYWxfQ2hhbmdlX3NpZywgY29sb3IgPSBEaXJlY3Rpb25hbF9DaGFuZ2Vfc2lnKSwgc3RhdCA9ICdpZGVudGl0eScsIHNoYXBlID0gMjEpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJ3aGl0ZSIsImJsYWNrIiwiZ3JleSIpLCBuYW1lID0gIkRpc3NpbWlsYXJpdHkgdHJlbmQiLCBndWlkZT0ibm9uZSIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiYmxhY2siLCJibGFjayIsImdyZXkiKSwgbmFtZSA9ICJEaXNzaW1pbGFyaXR5IHRyZW5kIiwgZ3VpZGU9Im5vbmUiKSArCiAgc2NhbGVfc2l6ZV9iaW5uZWQocmFuZ2UgPSBjKDEsOCksIG5hbWUgPSAiU3VydmV5IHBlcmlvZCBsZW5ndGgiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoLTAuMDA1LCAwLjAwNzUsIGJ5ID0gMC4wMDI1KSwgbGFiZWxzID0gYygiLTAuMDA1IiwiIiwiMCIsICIiLCAiMC4wMDUiLCAgIiIpKSArCiAgeGxhYigiU3VydmV5IHVuaXQiKSArCiAgeWxhYigizrItZGl2ZXJzaXR5IHRyZW5kIikgKyAjdG90YWwgQkMgZGlzc2ltaWxhcml0eSB0cmVuZAogIGNvb3JkX2ZsaXAoKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSBjb2xvcl95ZWFyX2Fkal9vcmRlciwgZmFjZSA9ICJib2xkIiksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4yNSwwLjcpLCBsZWdlbmQuZGlyZWN0aW9uID0gInZlcnRpY2FsIikKCiNwdWxsIGxlZ2VuZCBmb3IgaG9tb2dlbml6YXRpb24KZGlyZWN0aW9uYWxfY2hhbmdlX2xlZ2VuZF9wbG90IDwtIEJDX3RvdGFsX0Rpc3NpbWlsYXJpdHlfQ29lZl9lcnJvcmJhcl9yZWR1Y2VkICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygid2hpdGUiLCJibGFjayIsImdyZXkiKSwgbmFtZSA9ICJEaXNzaW1pbGFyaXR5IHRyZW5kIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJibGFjayIsImJsYWNrIiwiZ3JleSIpLCBuYW1lID0gIkRpc3NpbWlsYXJpdHkgdHJlbmQiKSArCiAgc2NhbGVfc2l6ZV9iaW5uZWQocmFuZ2UgPSBjKDEsOCksIG5hbWUgPSAiU3VydmV5IHBlcmlvZCBsZW5ndGgiLCBndWlkZSA9ICJub25lIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9ICJ0cmFuc3BhcmVudCIpKSArCiAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemU9NikpKQoKCkJDX3RvdGFsX0Rpc3NpbWlsYXJpdHlfQ29lZl9lcnJvcmJhcl9yZWR1Y2VkCgojQUxUIGdyZXkgc2NhbGUKQkNfdG90YWxfRGlzc2ltaWxhcml0eV9Db2VmX2Vycm9yYmFyX3JlZHVjZWRfZ3JleXNjYWxlIDwtIGdncGxvdCgpICsKICAgIGdlb21fZXJyb3JiYXIoZGF0YSA9IG1vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLCBhZXMoeCA9IHJlb3JkZXIoU3VydmV5X05hbWVfU2Vhc29uLCB5ZWFyX2FkaikgLCB5ID0geWVhcl9hZGosIGxhYmVsID0gU3VydmV5X05hbWVfU2Vhc29uLCB5bWluID0gbHdyLCB5bWF4ID0gdXByKSwgZmlsbCA9ICJncmV5Iiwgd2lkdGggPSAwKSArICNhZGQgY29uZmlkZW5jZSBpbnRlcnZhbHMKICBnZW9tX3BvaW50KGRhdGEgPSBtb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aCwgYWVzKHggPSByZW9yZGVyKFN1cnZleV9OYW1lX1NlYXNvbiwgeWVhcl9hZGopICwgeSA9IHllYXJfYWRqLCBsYWJlbCA9IFN1cnZleV9OYW1lX1NlYXNvbiwgc2l6ZSA9IHllYXJzX3NhbXBsZWQsIGZpbGwgPSBEaXJlY3Rpb25hbF9DaGFuZ2Vfc2lnLCBjb2xvciA9IERpcmVjdGlvbmFsX0NoYW5nZV9zaWcpLCBzdGF0ID0gJ2lkZW50aXR5Jywgc2hhcGUgPSAyMSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIndoaXRlIiwiYmxhY2siLCJncmV5IiksIG5hbWUgPSAiRGlzc2ltaWxhcml0eSB0cmVuZCIsIGd1aWRlPSJub25lIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJibGFjayIsImJsYWNrIiwiZ3JleSIpLCBuYW1lID0gIkRpc3NpbWlsYXJpdHkgdHJlbmQiLCBndWlkZT0ibm9uZSIpICsKICBzY2FsZV9zaXplX2Jpbm5lZChyYW5nZSA9IGMoMSw4KSwgbmFtZSA9ICJTdXJ2ZXkgcGVyaW9kIGxlbmd0aCIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgtMC4wMDUsIDAuMDA3NSwgYnkgPSAwLjAwMjUpLCBsYWJlbHMgPSBjKCItMC4wMDUiLCIiLCIwIiwgIiIsICIwLjAwNSIsICAiIikpICsKICB4bGFiKCJTdXJ2ZXkgdW5pdCIpICsKICB5bGFiKCLOsi1kaXZlcnNpdHkgdHJlbmQiKSArICN0b3RhbCBCQyBkaXNzaW1pbGFyaXR5IHRyZW5kCiAgY29vcmRfZmxpcCgpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLCBsZWdlbmQucG9zaXRpb24gPSBjKDAuMjUsMC43KSwgbGVnZW5kLmRpcmVjdGlvbiA9ICJ2ZXJ0aWNhbCIpCmBgYAoKV2F2eSBMaW5lIFBsb3QgZm9yIEdBTXMKCkdlbmVyYXRlIHByZWRpY3RlZCB2YWx1ZXMKYGBge3IgZ2VuZXJhdGUgcHJlZGljdGVkIHZhbHVlcyBHQU19CgojYWRkIGNvbG9ycyBhbmQgbmFtZXMgdG8gZnVsbCBkaXNzaW1pbGFyaXR5IGRhdGEgdGFibGUKZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yIDwtIGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMucltjb2xvcl9saW5rLCBvbiA9ICJzdXJ2ZXlfdW5pdCJdCgojZ2VuZXJhdGUgbmV3IGRhdGEgdG8gc21vb3RoIGxpbmVzIChuZWVkIHllYXIgYW5kIHNlYXNvbiBzdXJ2ZXkgY29tYmluYXRpb25zKQp5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdCA8LSBkYXRhLnRhYmxlKHN1cnZleV91bml0ID0gYXMuY2hhcmFjdGVyKE5VTEwpLCB5ZWFyID0gYXMubnVtZXJpYyhOVUxMKSwgeWVhcl9hZGogPSBhcy5udW1lcmljKE5VTEwgKSkKCmZvciAoaSBpbiAxOmxlbmd0aChzdXJ2ZXlfdW5pdC5saXN0KSkgewogICNnZW5lcmF0ZSB5ZWFyIHZlY3RvcnMKICBzdXJ2ZXlfdW5pdF95ZWFycyA8LSB1bmlxdWUoZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yW3N1cnZleV91bml0ID09IHN1cnZleV91bml0Lmxpc3RbaV0sLihzdXJ2ZXlfdW5pdCwgeWVhciwgeWVhcl9hZGopXSkKICAKICB5ZWFycyA8LSBzZXEobWluKHN1cnZleV91bml0X3llYXJzWyx5ZWFyXSksIG1heChzdXJ2ZXlfdW5pdF95ZWFyc1sseWVhcl0pLCBieSA9IDAuMSkKICAKICB5ZWFyX2FkanVzdCA8LSBzZXEobWluKHN1cnZleV91bml0X3llYXJzWyx5ZWFyX2Fkal0pLCBtYXgoc3VydmV5X3VuaXRfeWVhcnNbLHllYXJfYWRqXSksIGJ5ID0gMC4xKQogIAogIHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0X2FkZGl0aW9uIDwtIGRhdGEudGFibGUoc3VydmV5X3VuaXQgPSBzdXJ2ZXlfdW5pdC5saXN0W2ldLCB5ZWFyID0geWVhcnMsIHllYXJfYWRqID0geWVhcl9hZGp1c3QpCiAgCiAgeWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHQgPC0gcmJpbmQoeWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHQsIHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0X2FkZGl0aW9uKQp9CgojYWRkIGNvbG9ycyBhbmQgbmFtZXMgdG8gZnVsbCB5ZWFyIGFuZCBzdXJ2ZXkgdW5pdCBjb21iaW5hdGlvbiB0YWJsZQp5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdCA8LSB5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdFtjb2xvcl9saW5rLCBvbiA9ICJzdXJ2ZXlfdW5pdCJdCmBgYAoKCgpHZXQgbW9kZWwgYXMgcHJlZGljdGlvbnMKYGBge3J9CiNmb3IgcGxvdHRpbmcsIGdldCBtb2RlbCBhcyBwcmVkaWN0aW9ucwpicmF5X2N1cnRpc190b3RhbF9nYW1fcHJlZGljdGlvbnMgPC0gcHJlZGljdChicmF5X2N1cnRpc190b3RhbF9nYW0sIHNlLmZpdCA9IFRSVUUsIG5ld2RhdGEgPSB5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdCkKCiNtZXJnZSBpbnRvIHRhYmxlCnllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0WyxicmF5X2dsbV9tb2RfZml0IDo9IGJyYXlfY3VydGlzX3RvdGFsX2dhbV9wcmVkaWN0aW9ucyRmaXRdWyxicmF5X2dsbV9tb2RfZml0X1NFIDo9IGJyYXlfY3VydGlzX3RvdGFsX2dhbV9wcmVkaWN0aW9ucyRzZS5maXRdCgpgYGAKCgpQcm9kdWNlIFBsb3Qgb2YgR0FNIGFuZCBtZWFuIExNRVIgbGluZQpgYGB7ciBwbG90IEdBTSBhbmQgbWVhbiBMTUVSIGxpbmVzfQpwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbV9ub2xtZXIgPC0gZ2dwbG90KCkgKwogIyBnZW9tX3JpYmJvbihkYXRhID0gbG1lcl9icmF5X3RvdGFsX3ByZWRpY3Rpb25zLCBhZXMoeCA9IHllYXIsIHltaW4gPSBicmF5X2N1cnRpc19sbWVyX3ByZWRzX2xvd2VyQ0ksIHltYXggPSBicmF5X2N1cnRpc19sbWVyX3ByZWRzX3VwcGVyQ0kpLCBmaWxsID0gImdyZXkiLCBhbHBoYSA9IDAuMikgKwogIGdlb21fcG9pbnQoZGF0YSA9IG5hLm9taXQoZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yLGNvbHMgPSAieWVhcl9hZGoiKSwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuLAogICAgICAgICAgICAgICAgIGNvbG9yID0gU3VydmV5X05hbWVfU2Vhc29uKSwgYWxwaGEgPSAwLjUsIHNpemUgPSAxKSArCiAgICBnZW9tX2xpbmUoZGF0YSA9IG5hLm9taXQoeWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHQsY29scyA9ICJ5ZWFyX2FkaiIpLAogICAgICAgICAgICAgYWVzKHggPSB5ZWFyLAogICAgICAgICAgICAgICAgIHkgPSBicmF5X2dsbV9tb2RfZml0LAogICAgICAgICAgICAgICAgIGNvbG9yID0gU3VydmV5X05hbWVfU2Vhc29uKSkgKwogIGdlb21fcmliYm9uKGRhdGEgPSBuYS5vbWl0KHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0LGNvbHMgPSAieWVhcl9hZGoiKSwgYWVzKHggPSB5ZWFyLCB5bWluPWJyYXlfZ2xtX21vZF9maXQtYnJheV9nbG1fbW9kX2ZpdF9TRSwgeW1heD1icmF5X2dsbV9tb2RfZml0K2JyYXlfZ2xtX21vZF9maXRfU0UsIGZpbGwgPSAgU3VydmV5X05hbWVfU2Vhc29uKSwgYWxwaGE9MC4xKSArICNhZGQgc3RhbmRhcmQgZXJyb3IKICMgZ2VvbV9saW5lKGRhdGEgPSBsbWVyX2JyYXlfdG90YWxfcHJlZGljdGlvbnMsIGFlcyh4ID0geWVhciwgeSA9IGJyYXlfY3VydGlzX2xtZXJfcHJlZHMpLCBjb2xvciA9ICJibGFjayIpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSAgY29sb3JfYWxwaGFfb3JkZXIsIG5hbWUgPSAiU3VydmV5IFVuaXQiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gIGNvbG9yX2FscGhhX29yZGVyLCBndWlkZSA9ICJub25lIikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgbGltcyh4ID0gYyhtaW4oZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyXSksbWF4KGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl0pKSwKICAgICAgIHkgPSBjKDAuMTUsMC45KSkgKwogIHhsYWIoIlllYXIiKSArCnlsYWIoInRvdGFsIEJDIGRpc3NpbWlsYXJpdHkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm51bGwiKQoKcG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1fbm9sbWVyCgpnZ3NhdmUocG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1fbm9sbWVyLCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9InBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX25vbG1lci5qcGciLCBoZWlnaHQgPSA1LCB3aWR0aCA9IDUsIHVuaXQgPSAiaW4iKQoKI3dpdGggbG1lcgoKcG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW0gPC0gZ2dwbG90KCkgKwogIGdlb21fcmliYm9uKGRhdGEgPSBsbWVyX2JyYXlfdG90YWxfcHJlZGljdGlvbnMsIGFlcyh4ID0geWVhciwgeW1pbiA9IGJyYXlfY3VydGlzX2xtZXJfcHJlZHNfbG93ZXJDSSwgeW1heCA9IGJyYXlfY3VydGlzX2xtZXJfcHJlZHNfdXBwZXJDSSksIGZpbGwgPSAiZ3JleSIsIGFscGhhID0gMC4zKSArCiAgZ2VvbV9wb2ludChkYXRhID0gbmEub21pdChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnIsIGNvbHMgPSAieWVhcl9hZGoiKSwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuLAogICAgICAgICAgICAgICAgIGZpbGwgPSBTdXJ2ZXlfTmFtZV9TZWFzb24pLCBhbHBoYSA9IDAuNCwgc2l6ZSA9IDEsIHNoYXBlID0gMjEsIGNvbG9yID0gIndoaXRlIikgKwogICAgZ2VvbV9saW5lKGRhdGEgPSBuYS5vbWl0KHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0LCBjb2xzID0gInllYXJfYWRqIiksCiAgICAgICAgICAgICBhZXMoeCA9IHllYXIsCiAgICAgICAgICAgICAgICAgeSA9IGJyYXlfZ2xtX21vZF9maXQsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBTdXJ2ZXlfTmFtZV9TZWFzb24pLCBhbHBoYSA9IDAuNikgKwogIGdlb21fcmliYm9uKGRhdGEgPSBuYS5vbWl0KHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0LCBjb2xzID0gInllYXJfYWRqIiksIGFlcyh4ID0geWVhciwgeW1pbj1icmF5X2dsbV9tb2RfZml0LWJyYXlfZ2xtX21vZF9maXRfU0UsIHltYXg9YnJheV9nbG1fbW9kX2ZpdCticmF5X2dsbV9tb2RfZml0X1NFLCBmaWxsID0gIFN1cnZleV9OYW1lX1NlYXNvbiksIGFscGhhPTAuMSkgKyAjYWRkIHN0YW5kYXJkIGVycm9yCiAgZ2VvbV9saW5lKGRhdGEgPSBsbWVyX2JyYXlfdG90YWxfcHJlZGljdGlvbnMsIGFlcyh4ID0geWVhciwgeSA9IGJyYXlfY3VydGlzX2xtZXJfcHJlZHMpLCBjb2xvciA9ICJibGFjayIpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSAgY29sb3JfYWxwaGFfb3JkZXIsIG5hbWUgPSAiU3VydmV5IFVuaXQiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gIGNvbG9yX2FscGhhX29yZGVyLCBndWlkZSA9ICJub25lIikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgbGltcyh4ID0gYyhtaW4oZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyXSksbWF4KGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl0pKSkgKwogIHhsYWIoIlllYXIiKSArCnlsYWIoIs6yLWRpdmVyc2l0eSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibnVsbCIsIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLCBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSkpCgpwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbQoKZ2dzYXZlKHBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtLCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9InBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtLmpwZyIsIGhlaWdodCA9IDYsIHdpZHRoID0gNiwgdW5pdCA9ICJpbiIpCgojQUxUCiNwbG90IGFsbCwgYnV0IHNhbWUgY29sb3Igc2NoZW1lIChncmV5KQpwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbV9ncmV5c2NhbGUgPC0gZ2dwbG90KCkgKwogIGdlb21fcmliYm9uKGRhdGEgPSBsbWVyX2JyYXlfdG90YWxfcHJlZGljdGlvbnMsIGFlcyh4ID0geWVhciwgeW1pbiA9IGJyYXlfY3VydGlzX2xtZXJfcHJlZHNfbG93ZXJDSSwgeW1heCA9IGJyYXlfY3VydGlzX2xtZXJfcHJlZHNfdXBwZXJDSSksIGZpbGwgPSAiZ3JleSIsIGFscGhhID0gMC4zKSArCiAgZ2VvbV9wb2ludChkYXRhID0gZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yLAogICAgICAgICAgICAgYWVzKHggPSB5ZWFyLAogICAgICAgICAgICAgICAgIHkgPSBicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X3RvdGFsX21lYW4sCiAgICAgICAgICAgICAgICAgZmlsbCA9IFN1cnZleV9OYW1lX1NlYXNvbiksIGFscGhhID0gMC40LCBzaXplID0gMSwgc2hhcGUgPSAyMSwgY29sb3IgPSAid2hpdGUiKSArCiAgICBnZW9tX2xpbmUoZGF0YSA9IHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0LAogICAgICAgICAgICAgYWVzKHggPSB5ZWFyLAogICAgICAgICAgICAgICAgIHkgPSBicmF5X2dsbV9tb2RfZml0LAogICAgICAgICAgICAgICAgIGNvbG9yID0gU3VydmV5X05hbWVfU2Vhc29uKSwgYWxwaGEgPSAwLjYpICsKICBnZW9tX3JpYmJvbihkYXRhID0geWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHQsIGFlcyh4ID0geWVhciwgeW1pbj1icmF5X2dsbV9tb2RfZml0LWJyYXlfZ2xtX21vZF9maXRfU0UsIHltYXg9YnJheV9nbG1fbW9kX2ZpdCticmF5X2dsbV9tb2RfZml0X1NFLCBmaWxsID0gIFN1cnZleV9OYW1lX1NlYXNvbiksIGFscGhhPTAuMSkgKyAjYWRkIHN0YW5kYXJkIGVycm9yCiAgZ2VvbV9saW5lKGRhdGEgPSBsbWVyX2JyYXlfdG90YWxfcHJlZGljdGlvbnMsIGFlcyh4ID0geWVhciwgeSA9IGJyYXlfY3VydGlzX2xtZXJfcHJlZHMpLCBjb2xvciA9ICJibGFjayIpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSAgcmVwKCJibGFjayIsIHRpbWVzID0gbGVuZ3RoKHVuaXF1ZShkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnIkU3VydmV5X05hbWVfU2Vhc29uKSkpLCBuYW1lID0gIlN1cnZleSBVbml0IikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9ICByZXAoImJsYWNrIiwgdGltZXMgPSBsZW5ndGgodW5pcXVlKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuciRTdXJ2ZXlfTmFtZV9TZWFzb24pKSksIGd1aWRlID0gIm5vbmUiKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICBsaW1zKHggPSBjKG1pbihkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLHllYXJdKSxtYXgoZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyXSkpCiAgICAgICApICsKICB4bGFiKCJZZWFyIikgKwp5bGFiKCLOsi1kaXZlcnNpdHkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm51bGwiLCBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpKQoKcG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1fZ3JleXNjYWxlCgpnZ3NhdmUocG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1fZ3JleXNjYWxlLCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9InBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX2dyZXlzY2FsZS5qcGciLCBoZWlnaHQgPSA2LCB3aWR0aCA9IDYsIHVuaXQgPSAiaW4iKQoKCiNwbG90IGVhY2ggaW5kZXBlbmRlbnRseSBmb3Igc3VwcGxlbWVudAojYWxsIHN1cnZleSBuYW1lcyA9IAphbGxfc3VydmV5X25hbWVzIDwtIHNvcnQodW5pcXVlKGNvbG9yX2xpbmskU3VydmV5X05hbWVfU2Vhc29uKSkKI2xpc3Qgb2YgcGxvdHMKcG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1faW5kaXZpZHVhbCA8LSBsaXN0KCkKZm9yIChpIGluIDE6bGVuZ3RoKGFsbF9zdXJ2ZXlfbmFtZXMpKSB7CnBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX2luZGl2aWR1YWxbW2ldXSA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9wb2ludChkYXRhID0gZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yW1N1cnZleV9OYW1lX1NlYXNvbiA9PSBhbGxfc3VydmV5X25hbWVzW2ldXSwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuKSwgYWxwaGEgPSAwLjQsIGNvbG9yID0gImJsYWNrIikgKwogICAgZ2VvbV9saW5lKGRhdGEgPSB5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdFtTdXJ2ZXlfTmFtZV9TZWFzb24gPT0gYWxsX3N1cnZleV9uYW1lc1tpXV0sCiAgICAgICAgICAgICBhZXMoeCA9IHllYXIsCiAgICAgICAgICAgICAgICAgeSA9IGJyYXlfZ2xtX21vZF9maXQpLCBhbHBoYSA9IDAuNikgKwogIGdlb21fcmliYm9uKGRhdGEgPSB5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdFtTdXJ2ZXlfTmFtZV9TZWFzb24gPT0gYWxsX3N1cnZleV9uYW1lc1tpXV0sIGFlcyh4ID0geWVhciwgeW1pbj1icmF5X2dsbV9tb2RfZml0LWJyYXlfZ2xtX21vZF9maXRfU0UsIHltYXg9YnJheV9nbG1fbW9kX2ZpdCticmF5X2dsbV9tb2RfZml0X1NFKSwgYWxwaGE9MC4xKSArICNhZGQgc3RhbmRhcmQgZXJyb3IKICB0aGVtZV9jbGFzc2ljKCkgKwojICBsaW1zKHggPSBjKG1pbihkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbU3VydmV5X05hbWVfU2Vhc29uID09IGFsbF9zdXJ2ZXlfbmFtZXNbaV0seWVhcl0pLG1heChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbU3VydmV5X05hbWVfU2Vhc29uID09IGFsbF9zdXJ2ZXlfbmFtZXNbaV0seWVhcl0pKSwKIyAgICAgICB5ID0gYygwLjE1LDAuOSkpICsKICB4bGFiKCJZZWFyIikgKwp5bGFiKCJiZXRhLWRpdmVyc2l0eSIpICsKICBmYWNldF93cmFwKH5TdXJ2ZXlfTmFtZV9TZWFzb24sIG5jb2wgPSA1KSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm51bGwiLCBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpKQoKcHJpbnQocG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1faW5kaXZpZHVhbFtbaV1dKQoKfQpzYXZlUkRTKHBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX2luZGl2aWR1YWwsIGhlcmU6OmhlcmUoImZpZ3VyZXMiLCJwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbV9pbmRpdmlkdWFsLlJkcyIpKQoKI3ByaW50IHRvIHBkZgpsaWJyYXJ5KGdyaWRFeHRyYSkKCmdnc2F2ZSgKICAgZmlsZW5hbWUgPSBoZXJlOjpoZXJlKCJmaWd1cmVzIiwicG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1faW5kaXZpZHVhbC5wZGYiKSwgCiAgIHBsb3QgPSBtYXJyYW5nZUdyb2IocG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1faW5kaXZpZHVhbCwgbnJvdz0xLCBuY29sPTEpLCAKICAgd2lkdGggPSA4LjUsIGhlaWdodCA9IDExCikKCgpgYGAKClJlZ2lvbiBieSByZWdpb24gYnVpbGQgdXAKYGBge3IgcmVnaW9uIGJ1aWxkIHVwfQojanVzdCBFQlMgZm9yIHBlcnNvbmFsIGludGVyZXN0CnBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX0VCU19vbmx5IDwtIGdncGxvdCgpICsKICBnZW9tX3BvaW50KGRhdGEgPSBkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbc3VydmV5X3VuaXQgPT0gIkVCUyIsXSwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuKSwgYWxwaGEgPSAwLjUsIHNpemUgPSAxCiAgICAgICAgICAgICMgLCAKICAgICAgICAgICAgIyBjb2xvciA9IEJDX3RvdGFsX21vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLnVuaXF1ZVtTdXJ2ZXlfTmFtZV9TZWFzb24gPT0gIkVhc3Rlcm4gQmVyaW5nIFNlYSIsaGV4XQogICAgICAgICAgICAgKSArCiAgIyAgZ2VvbV9saW5lKGRhdGEgPSB5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdFtzdXJ2ZXlfdW5pdCA9PSAiRUJTIixdLAogICAjICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICMgICAgICAgICAgICAgeSA9IGJyYXlfZ2xtX21vZF9maXQpLAogICAgICMgICAgICAgIGNvbG9yID0gQkNfdG90YWxfbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgudW5pcXVlW1N1cnZleV9OYW1lX1NlYXNvbiA9PSAiRWFzdGVybiBCZXJpbmcgU2VhIixoZXhdKSArCiAjIGdlb21fcmliYm9uKGRhdGEgPSB5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdFtzdXJ2ZXlfdW5pdCA9PSAiRUJTIixdLCBhZXMoeCA9IHllYXIsIHltaW49YnJheV9nbG1fbW9kX2ZpdC1icmF5X2dsbV9tb2RfZml0X1NFLCB5bWF4PWJyYXlfZ2xtX21vZF9maXQrYnJheV9nbG1fbW9kX2ZpdF9TRSksIGFscGhhPTAuMywgZmlsbCA9IEJDX3RvdGFsX21vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLnVuaXF1ZVtTdXJ2ZXlfTmFtZV9TZWFzb24gPT0gIkVhc3Rlcm4gQmVyaW5nIFNlYSIsaGV4XSkgKyAjYWRkIHN0YW5kYXJkIGVycm9yCiAjIGdlb21fbGluZShkYXRhID0gbG1lcl9icmF5X3RvdGFsX3ByZWRpY3Rpb25zLCBhZXMoeCA9IHllYXIsIHkgPSBicmF5X2N1cnRpc19sbWVyX3ByZWRzKSwgY29sb3IgPSAiYmxhY2siKSArCiAgIyAgc2NhbGVfY29sb3JfbWFudWFsKG5hbWUgPSAiU3VydmV5IFVuaXQiKSArCiAjIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9ICBwYWxldHRlXzQyLCBndWlkZSA9ICJub25lIikgKwogIyAgIGxpbXMoeCA9IGMobWluKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl0pLG1heChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLHllYXJdKSksCiAjICAgICAgeSA9IGMoMC4xNSwwLjkpKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB4bGFiKCJZZWFyIikgKwp5bGFiKCJ0b3RhbCBCQyBkaXNzaW1pbGFyaXR5IikKCnBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX0VCU19vbmx5CgojanVzdCBvbmUgcmVnaW9uIHRoYXQncyBob21vZ2VuaXppbmcgKE5aIFdDU0kpCnBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX05aX29ubHkgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMucltzdXJ2ZXlfdW5pdCA9PSAiTlotV0NTSSIsXSwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuKSwgYWxwaGEgPSAwLjUsIHNpemUgPSAxLCBjb2xvciA9IEJDX3RvdGFsX21vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLnVuaXF1ZVtTdXJ2ZXlfTmFtZV9TZWFzb24gPT0gIlcgQ29hc3QgUyBJc2xhbmQgTloiLGhleF0pICsKICAgIGdlb21fbGluZShkYXRhID0geWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHRbc3VydmV5X3VuaXQgPT0gIk5aLVdDU0kiLF0sCiAgICAgICAgICAgICBhZXMoeCA9IHllYXIsCiAgICAgICAgICAgICAgICAgeSA9IGJyYXlfZ2xtX21vZF9maXQpLAogICAgICAgICAgICAgY29sb3IgPSBCQ190b3RhbF9tb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aC51bmlxdWVbU3VydmV5X05hbWVfU2Vhc29uID09ICJXIENvYXN0IFMgSXNsYW5kIE5aIixoZXhdKSArCiAgZ2VvbV9yaWJib24oZGF0YSA9IHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0W3N1cnZleV91bml0ID09ICJOWi1XQ1NJIixdLCBhZXMoeCA9IHllYXIsIHltaW49YnJheV9nbG1fbW9kX2ZpdC1icmF5X2dsbV9tb2RfZml0X1NFLCB5bWF4PWJyYXlfZ2xtX21vZF9maXQrYnJheV9nbG1fbW9kX2ZpdF9TRSksIGFscGhhPTAuMywgZmlsbCA9IEJDX3RvdGFsX21vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLnVuaXF1ZVtTdXJ2ZXlfTmFtZV9TZWFzb24gPT0gIlcgQ29hc3QgUyBJc2xhbmQgTloiLGhleF0pICsgI2FkZCBzdGFuZGFyZCBlcnJvcgogIyBnZW9tX2xpbmUoZGF0YSA9IGxtZXJfYnJheV90b3RhbF9wcmVkaWN0aW9ucywgYWVzKHggPSB5ZWFyLCB5ID0gYnJheV9jdXJ0aXNfbG1lcl9wcmVkcyksIGNvbG9yID0gImJsYWNrIikgKwogICAgc2NhbGVfY29sb3JfbWFudWFsKG5hbWUgPSAiU3VydmV5IFVuaXQiKSArCiAjIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9ICBwYWxldHRlXzQyLCBndWlkZSA9ICJub25lIikgKwogICAgbGltcyh4ID0gYyhtaW4oZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyXSksbWF4KGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl0pKSwKICAgICAgIHkgPSBjKDAuMTUsMC45KSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgeGxhYigiWWVhciIpICsKeWxhYigidG90YWwgQkMgZGlzc2ltaWxhcml0eSIpCgpwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbV9OWl9vbmx5CgojanVzdCB0d28gcmVnaW9ucywgYW5vdGhlciB0aGF0J3MgZGlmZmVyZW50aWF0aW5nIChTRVVTIFN1bW1lcikKCnBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX05aX1NFVVNfU3VtbWVyX29ubHkgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMucltzdXJ2ZXlfdW5pdCAlaW4lIGMoIk5aLVdDU0kiLCJTRVVTLXN1bW1lciIpLF0sCiAgICAgICAgICAgICBhZXMoeCA9IHllYXIsCiAgICAgICAgICAgICAgICAgeSA9IGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfdG90YWxfbWVhbiwKICAgICAgICAgICAgICAgICBjb2xvciA9IFN1cnZleV9OYW1lX1NlYXNvbiksIGFscGhhID0gMC41LCBzaXplID0gMSkgKwogICAgZ2VvbV9saW5lKGRhdGEgPSB5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdFtzdXJ2ZXlfdW5pdCAlaW4lIGMoIk5aLVdDU0kiLCJTRVVTLXN1bW1lciIpLF0sCiAgICAgICAgICAgICBhZXMoeCA9IHllYXIsCiAgICAgICAgICAgICAgICAgeSA9IGJyYXlfZ2xtX21vZF9maXQsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBTdXJ2ZXlfTmFtZV9TZWFzb24pKSArCiAgZ2VvbV9yaWJib24oZGF0YSA9IHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0W3N1cnZleV91bml0ICVpbiUgYygiTlotV0NTSSIsIlNFVVMtc3VtbWVyIiksXSwgYWVzKHggPSB5ZWFyLCB5bWluPWJyYXlfZ2xtX21vZF9maXQtYnJheV9nbG1fbW9kX2ZpdF9TRSwgeW1heD1icmF5X2dsbV9tb2RfZml0K2JyYXlfZ2xtX21vZF9maXRfU0UsIGZpbGwgPSBzdXJ2ZXlfdW5pdCksIGFscGhhPTAuMykgKyAjYWRkIHN0YW5kYXJkIGVycm9yCiAjIGdlb21fbGluZShkYXRhID0gbG1lcl9icmF5X3RvdGFsX3ByZWRpY3Rpb25zLCBhZXMoeCA9IHllYXIsIHkgPSBicmF5X2N1cnRpc19sbWVyX3ByZWRzKSwgY29sb3IgPSAiYmxhY2siKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwobmFtZSA9ICJTdXJ2ZXkgVW5pdCIsIHZhbHVlcyA9IGMoQkNfdG90YWxfbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgudW5pcXVlW1N1cnZleV9OYW1lX1NlYXNvbiAlaW4lIGMoIlcgQ29hc3QgUyBJc2xhbmQgTloiLCJTRSBVUyBTdW1tZXIiKSxoZXhdKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKGd1aWRlID0gIm5vbmUiLCB2YWx1ZXMgPSBjKEJDX3RvdGFsX21vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLnVuaXF1ZVtTdXJ2ZXlfTmFtZV9TZWFzb24gJWluJSBjKCJXIENvYXN0IFMgSXNsYW5kIE5aIiwiU0UgVVMgU3VtbWVyIiksaGV4XSkpICsKICAgIGxpbXMoeCA9IGMobWluKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl0pLG1heChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLHllYXJdKSksCiAgICAgICB5ID0gYygwLjE1LDAuOSkpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHhsYWIoIlllYXIiKSArCnlsYWIoInRvdGFsIEJDIGRpc3NpbWlsYXJpdHkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm51bGwiKQoKcG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1fTlpfU0VVU19TdW1tZXJfb25seQoKI2p1c3QgdGhyZWUgcmVnaW9ucywgYW5vdGhlciBvbmUgdGhhdCdzIHN0YWJsZSwgKENhbmFkYSBTY290aWFuIFNoZWxmKQoKcG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1fTlpfU0VVU19TY29TaGVsZl9vbmx5IDwtIGdncGxvdCgpICsKICBnZW9tX3BvaW50KGRhdGEgPSBkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbc3VydmV5X3VuaXQgJWluJSBjKCJOWi1XQ1NJIiwiU0VVUy1zdW1tZXIiLCAiU0NTLVNVTU1FUiIpLF0sCiAgICAgICAgICAgICBhZXMoeCA9IHllYXIsCiAgICAgICAgICAgICAgICAgeSA9IGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfdG90YWxfbWVhbiwKICAgICAgICAgICAgICAgICBjb2xvciA9IFN1cnZleV9OYW1lX1NlYXNvbiksIGFscGhhID0gMC41LCBzaXplID0gMSkgKwogICAgZ2VvbV9saW5lKGRhdGEgPSB5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdFtzdXJ2ZXlfdW5pdCAlaW4lIGMoIk5aLVdDU0kiLCJTRVVTLXN1bW1lciIsIlNDUy1TVU1NRVIiKSxdLAogICAgICAgICAgICAgYWVzKHggPSB5ZWFyLAogICAgICAgICAgICAgICAgIHkgPSBicmF5X2dsbV9tb2RfZml0LAogICAgICAgICAgICAgICAgIGNvbG9yID0gU3VydmV5X05hbWVfU2Vhc29uKSkgKwogIGdlb21fcmliYm9uKGRhdGEgPSB5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdFtzdXJ2ZXlfdW5pdCAlaW4lIGMoIk5aLVdDU0kiLCJTRVVTLXN1bW1lciIsIlNDUy1TVU1NRVIiKSxdLCBhZXMoeCA9IHllYXIsIHltaW49YnJheV9nbG1fbW9kX2ZpdC1icmF5X2dsbV9tb2RfZml0X1NFLCB5bWF4PWJyYXlfZ2xtX21vZF9maXQrYnJheV9nbG1fbW9kX2ZpdF9TRSwgZmlsbCA9IFN1cnZleV9OYW1lX1NlYXNvbiksIGFscGhhPTAuMykgKyAjYWRkIHN0YW5kYXJkIGVycm9yCiAjIGdlb21fbGluZShkYXRhID0gbG1lcl9icmF5X3RvdGFsX3ByZWRpY3Rpb25zLCBhZXMoeCA9IHllYXIsIHkgPSBicmF5X2N1cnRpc19sbWVyX3ByZWRzKSwgY29sb3IgPSAiYmxhY2siKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwobmFtZSA9ICJTdXJ2ZXkgVW5pdCIsIHZhbHVlcyA9IGMoQkNfdG90YWxfbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgudW5pcXVlW1N1cnZleV9OYW1lX1NlYXNvbiAlaW4lIGMoIlcgQ29hc3QgUyBJc2xhbmQgTloiLCJTRSBVUyBTdW1tZXIiLCJTY290aWFuIFNoZWxmIiksaGV4XSkpICsKICBzY2FsZV9maWxsX21hbnVhbChndWlkZSA9ICJub25lIiwgdmFsdWVzID0gYyhCQ190b3RhbF9tb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aC51bmlxdWVbU3VydmV5X05hbWVfU2Vhc29uICVpbiUgYygiVyBDb2FzdCBTIElzbGFuZCBOWiIsIlNFIFVTIFN1bW1lciIsIlNjb3RpYW4gU2hlbGYiKSxoZXhdKSkgKwogICAgbGltcyh4ID0gYyhtaW4oZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyXSksbWF4KGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl0pKSwKICAgICAgIHkgPSBjKDAuMTUsMC45KSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgeGxhYigiWWVhciIpICsKeWxhYigidG90YWwgQkMgZGlzc2ltaWxhcml0eSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibnVsbCIpCgpwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbV9OWl9TRVVTX1Njb1NoZWxmX29ubHkKCmdnc2F2ZShwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbV9OWl9vbmx5LCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9InBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX05aX29ubHkuanBnIiwgaGVpZ2h0ID0gNSwgd2lkdGggPSA1LCB1bml0ID0gImluIikKZ2dzYXZlKHBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX0VCU19vbmx5LCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9InBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX0VCU19vbmx5LmpwZyIsIGhlaWdodCA9IDUsIHdpZHRoID0gOSwgdW5pdCA9ICJpbiIpCmdnc2F2ZShwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbV9OWl9TRVVTX1N1bW1lcl9vbmx5LCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9InBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX05aX1NFVVNfU3VtbWVyX29ubHkuanBnIiwgaGVpZ2h0ID0gNSwgd2lkdGggPSA1LCB1bml0ID0gImluIikKZ2dzYXZlKHBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX05aX1NFVVNfU2NvU2hlbGZfb25seSwgcGF0aCA9IGhlcmU6OmhlcmUoImZpZ3VyZXMiKSwgZmlsZW5hbWUgPSJwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbV9OWl9TRVVTX1Njb1NoZWxmX29ubHkuanBnIiwgaGVpZ2h0ID0gNSwgd2lkdGggPSA1LCB1bml0ID0gImluIikKCgoKCmBgYAoKTWVyZ2UgQkMgdmVyc3VzIFllYXIgcGxvdCB3aXRoIEdBTVMgYW5kIFJlZ2lvbiB2cy4gY29lZmZpY2llbnQgcGxvdCBmb3IgTE1FUnMKCmBgYHtyfQoKQkNfdG90YWxfR0FNX0xNRVJfbWVyZ2VfbGVnZW5kIDwtIGdnZHJhdyh4bGltID0gYygwLCA0MC41KSwgeWxpbSA9IGMoMCwgMjEpKSArCiAgICBkcmF3X3Bsb3QocG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IDEsIHkgPSAxLCB3aWR0aCA9IDIwLCBoZWlnaHQgPSAyMCkgKwogICAgZHJhd19wbG90KEJDX3RvdGFsX0Rpc3NpbWlsYXJpdHlfQ29lZl9lcnJvcmJhcl9yZWR1Y2VkICsKICAgICAgICB0aGVtZShsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuNSwgJ2NtJyksICNjaGFuZ2UgbGVnZW5kIGtleSBzaXplCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLCAjY2hhbmdlIGxlZ2VuZCB0aXRsZSBmb250IHNpemUKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSksICNjaGFuZ2UgbGVnZW5kIHRleHQgZm9udCBzaXplKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gMjAsIHkgPSAxLCB3aWR0aCA9MTksIGhlaWdodCA9IDIwKSArCiAgICBkcmF3X3Bsb3QoZ2V0X2xlZ2VuZChkaXJlY3Rpb25hbF9jaGFuZ2VfbGVnZW5kX3Bsb3QgKyAKICAgICAgdGhlbWUobGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjUsICdjbScpLCAjY2hhbmdlIGxlZ2VuZCBrZXkgc2l6ZQogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE1KSwgI2NoYW5nZSBsZWdlbmQgdGl0bGUgZm9udCBzaXplCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xMykpKSwgI2NoYW5nZSBsZWdlbmQgdGV4dCBmb250IHNpemUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSAyNywgeSA9IDEwLCB3aWR0aCA9IDMsIGhlaWdodCA9IDIpICsKICBnZW9tX3RleHQoYWVzKHggPSAyLCB5ID0gMjAuNyksIGxhYmVsID0gKCJhLiIpLCBzaXplID04LCBmb250ZmFjZSA9ICJib2xkIikgKwogIGdlb21fdGV4dChhZXMoeCA9MjAsIHkgPSAyMC43KSwgbGFiZWwgPSAoImIuIiksIHNpemUgPTgsIGZvbnRmYWNlID0gImJvbGQiKQoKCmdnc2F2ZShCQ190b3RhbF9HQU1fTE1FUl9tZXJnZV9sZWdlbmQsIHBhdGggPSBoZXJlOjpoZXJlKCJmaWd1cmVzIiksIGZpbGVuYW1lID0gIkJDX3RvdGFsX0dBTV9MTUVSX21lcmdlX2xlZ2VuZC5wbmciLCBoZWlnaHQgPSA4LCB3aWR0aCA9IDE0LCB1bml0cyA9ICJpbiIpCgojQUxUIEdSRVkgU0NBTEUKQkNfdG90YWxfR0FNX0xNRVJfbWVyZ2VfbGVnZW5kX2dyZXlzY2FsZSA8LSBnZ2RyYXcoeGxpbSA9IGMoMCwgNDAuNSksIHlsaW0gPSBjKDAsIDIxKSkgKwogICAgZHJhd19wbG90KHBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX2dyZXlzY2FsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gMSwgeSA9IDEsIHdpZHRoID0gMjAsIGhlaWdodCA9IDIwKSArCiAgICBkcmF3X3Bsb3QoQkNfdG90YWxfRGlzc2ltaWxhcml0eV9Db2VmX2Vycm9yYmFyX3JlZHVjZWRfZ3JleXNjYWxlICsKICAgICAgICB0aGVtZShsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuNSwgJ2NtJyksICNjaGFuZ2UgbGVnZW5kIGtleSBzaXplCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLCAjY2hhbmdlIGxlZ2VuZCB0aXRsZSBmb250IHNpemUKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSksICNjaGFuZ2UgbGVnZW5kIHRleHQgZm9udCBzaXplKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gMjAsIHkgPSAxLCB3aWR0aCA9IDE5LCBoZWlnaHQgPSAyMCkgKwogICAgZHJhd19wbG90KGdldF9sZWdlbmQoZGlyZWN0aW9uYWxfY2hhbmdlX2xlZ2VuZF9wbG90ICsgCiAgICAgIHRoZW1lKGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC41LCAnY20nKSwgI2NoYW5nZSBsZWdlbmQga2V5IHNpemUKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNSksICNjaGFuZ2UgbGVnZW5kIHRpdGxlIGZvbnQgc2l6ZQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTMpKSksICNjaGFuZ2UgbGVnZW5kIHRleHQgZm9udCBzaXplKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSAyNywgeSA9IDEwLCB3aWR0aCA9IDMsIGhlaWdodCA9IDIpICsKICBnZW9tX3RleHQoYWVzKHggPSAyLCB5ID0gMjAuNyksIGxhYmVsID0gKCJhLiIpLCBzaXplID04LCBmb250ZmFjZSA9ICJib2xkIikgKwogIGdlb21fdGV4dChhZXMoeCA9MjAsIHkgPSAyMC43KSwgbGFiZWwgPSAoImIuIiksIHNpemUgPTgsIGZvbnRmYWNlID0gImJvbGQiKQoKZ2dzYXZlKEJDX3RvdGFsX0dBTV9MTUVSX21lcmdlX2xlZ2VuZF9ncmV5c2NhbGUsIHBhdGggPSBoZXJlOjpoZXJlKCJmaWd1cmVzIiksIGZpbGVuYW1lID0gIkJDX3RvdGFsX0dBTV9MTUVSX21lcmdlX2xlZ2VuZF9ncmV5c2NhbGUucG5nIiwgaGVpZ2h0ID0gOCwgd2lkdGggPSAxNCwgdW5pdHMgPSAiaW4iKQoKCmBgYAoK